# PostgreSQL Advanced Queries and Optimization
PostgreSQL offers powerful features for complex data analysis. Here are some advanced query techniques:
-- Common Table Expressions (CTEs) for readable complex queriesWITH monthly_sales AS ( SELECT DATE_TRUNC('month', order_date) as month, SUM(total_amount) as monthly_total, COUNT(*) as order_count FROM orders WHERE order_date >= '2024-01-01' GROUP BY DATE_TRUNC('month', order_date)),growth_metrics AS ( SELECT month, monthly_total, LAG(monthly_total) OVER (ORDER BY month) as previous_month, monthly_total - LAG(monthly_total) OVER (ORDER BY month) as growth FROM monthly_sales)SELECT month, monthly_total, ROUND((growth / previous_month) * 100, 2) as growth_percentageFROM growth_metricsWHERE previous_month IS NOT NULLORDER BY month;
Window functions for analytical queries:
-- Ranking and analytical functionsSELECT product_name, category, price, -- Ranking within each category RANK() OVER (PARTITION BY category ORDER BY price DESC) as price_rank, -- Running total SUM(price) OVER (PARTITION BY category ORDER BY price ROWS UNBOUNDED PRECEDING) as running_total, -- Moving average (3-row window) AVG(price) OVER (PARTITION BY category ORDER BY price ROWS 2 PRECEDING) as moving_avg, -- Percentage of category total ROUND(price / SUM(price) OVER (PARTITION BY category) * 100, 2) as pct_of_categoryFROM productsORDER BY category, price DESC;
JSON operations and indexing:
-- Working with JSON dataCREATE TABLE user_profiles ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, profile_data JSONB NOT NULL, created_at TIMESTAMP DEFAULT NOW());
-- Create GIN index for JSON queriesCREATE INDEX idx_profile_data_gin ON user_profiles USING GIN (profile_data);
-- JSON queries and operationsINSERT INTO user_profiles (user_id, profile_data) VALUES(1, '{"name": "John Doe", "age": 30, "skills": ["Java", "Python"], "address": {"city": "New York", "country": "USA"}}');
SELECT user_id, profile_data->>'name' as name, profile_data->'address'->>'city' as city, jsonb_array_length(profile_data->'skills') as skill_countFROM user_profilesWHERE profile_data @> '{"address": {"country": "USA"}}';
Query optimization and performance analysis:
-- Analyze query performanceEXPLAIN (ANALYZE, BUFFERS)SELECT u.name, COUNT(o.id) as order_countFROM users uLEFT JOIN orders o ON u.id = o.user_idWHERE u.created_at >= '2024-01-01'GROUP BY u.id, u.nameHAVING COUNT(o.id) > 5ORDER BY order_count DESC;
-- Create optimized indexesCREATE INDEX CONCURRENTLY idx_users_created_at ON users (created_at);CREATE INDEX CONCURRENTLY idx_orders_user_date ON orders (user_id, order_date);
# Connect to PostgreSQLpsql -h localhost -U admin -d myapp
# Run SQL filepsql -h localhost -U admin -d myapp -f queries.sql
# Backup and restorepg_dump -h localhost -U admin myapp > backup.sqlpsql -h localhost -U admin -d myapp_restored < backup.sql