Advanced SQL Techniques for Modern Applications

Master advanced SQL techniques including window functions, CTEs, performance optimization, and working with JSON data

By · · Updated · 2 min read · intermediate

Learn powerful SQL techniques for building high-performance database queries and optimizations.

Window Functions

Window functions are powerful tools for analyzing data across rows:

WITH monthly_sales AS (
  SELECT 
    date_trunc('month', order_date) as month,
    product_id,
    SUM(amount) as total_sales,
    -- Calculate running total per product
    SUM(SUM(amount)) OVER (
      PARTITION BY product_id 
      ORDER BY date_trunc('month', order_date)
    ) as running_total,
    -- Calculate percent of total sales
    SUM(amount) / SUM(SUM(amount)) OVER (
      PARTITION BY product_id
    ) * 100 as percentage_of_total
  FROM orders
  GROUP BY 1, 2
)
SELECT * FROM monthly_sales;

Common Table Expressions (CTEs)

Use CTEs to break down complex queries into manageable pieces:

WITH active_users AS (
  SELECT user_id
  FROM user_sessions
  WHERE last_active > NOW() - INTERVAL '30 days'
),
user_purchases AS (
  SELECT 
    user_id,
    COUNT(*) as purchase_count,
    SUM(amount) as total_spent
  FROM orders
  WHERE order_date > NOW() - INTERVAL '90 days'
  GROUP BY user_id
)
SELECT 
  u.name,
  COALESCE(up.purchase_count, 0) as purchases,
  COALESCE(up.total_spent, 0) as spent
FROM users u
JOIN active_users au ON u.id = au.user_id
LEFT JOIN user_purchases up ON u.id = up.user_id;

Performance Optimization

Indexing Strategies

-- Create composite index for common query patterns
CREATE INDEX idx_orders_user_date ON orders (user_id, order_date);

-- Create partial index for active items
CREATE INDEX idx_active_items ON products (id)
WHERE status = 'active';

-- Create covering index for frequent queries
CREATE INDEX idx_users_email_name ON users (email)
INCLUDE (first_name, last_name);

Query Optimization

-- Use EXISTS instead of IN for better performance
SELECT *
FROM orders o
WHERE EXISTS (
  SELECT 1 
  FROM premium_users pu 
  WHERE pu.user_id = o.user_id
);

-- Use EXPLAIN ANALYZE to understand query performance
EXPLAIN ANALYZE
SELECT 
  p.category,
  COUNT(*) as order_count,
  AVG(o.amount) as avg_amount
FROM orders o
JOIN products p ON o.product_id = p.id
WHERE o.order_date >= NOW() - INTERVAL '1 month'
GROUP BY p.category
HAVING COUNT(*) > 100;

Working with JSON

Modern applications often need to work with JSON data:

-- Create a table with JSONB column
CREATE TABLE user_preferences (
  user_id UUID PRIMARY KEY,
  preferences JSONB NOT NULL
);

-- Query JSON data
SELECT 
  user_id,
  preferences->>'theme' as theme,
  preferences->'notifications'->>'email' as email_notifications
FROM user_preferences
WHERE preferences @> '{"theme": "dark"}';

-- Update JSON data
UPDATE user_preferences
SET preferences = preferences || 
  '{"notifications": {"email": true, "push": false}}'::jsonb
WHERE user_id = 'some-uuid';

Materialized Views

Use materialized views for complex reporting queries:

CREATE MATERIALIZED VIEW monthly_sales_report AS
SELECT 
  date_trunc('month', order_date) as month,
  p.category,
  COUNT(*) as order_count,
  SUM(o.amount) as total_sales,
  AVG(o.amount) as avg_order_value
FROM orders o
JOIN products p ON o.product_id = p.id
GROUP BY 1, 2
WITH DATA;

-- Create unique index for faster refreshes
CREATE UNIQUE INDEX idx_monthly_sales_report 
ON monthly_sales_report (month, category);

-- Refresh the materialized view
REFRESH MATERIALIZED VIEW CONCURRENTLY monthly_sales_report;