Multiple Conditional Aggregates

Calculate multiple aggregates with different conditions in a single pass through the data using CASE expressions.

Problem

You need to calculate various metrics from the same dataset with different conditions:

  • Count of buy orders
  • Count of sell orders
  • Average buy price
  • Average sell price
  • Total volume for large trades (> 1.0)
  • Total volume for small trades (≤ 1.0)

Running separate queries is inefficient.

Solution: CASE Within Aggregate Functions

Use CASE expressions inside aggregates to calculate all metrics in one query:

Multiple conditional aggregates in single queryDemo this query
SELECT
symbol,
count(CASE WHEN side = 'buy' THEN 1 END) as buy_count,
count(CASE WHEN side = 'sell' THEN 1 END) as sell_count,
avg(CASE WHEN side = 'buy' THEN price END) as avg_buy_price,
avg(CASE WHEN side = 'sell' THEN price END) as avg_sell_price,
sum(CASE WHEN amount > 1.0 THEN amount END) as large_trade_volume,
sum(CASE WHEN amount <= 1.0 THEN amount END) as small_trade_volume,
sum(amount) as total_volume
FROM trades
WHERE timestamp >= dateadd('d', -1, now())
AND symbol IN ('BTC-USDT', 'ETH-USDT')
GROUP BY symbol;

How It Works

CASE Returns NULL for Non-Matching Rows

count(CASE WHEN side = 'buy' THEN 1 END)
  • When side = 'buy': CASE returns 1
  • When side != 'buy': CASE returns NULL (implicit ELSE NULL)
  • count() only counts non-NULL values
  • Result: counts only rows where side is 'buy'

Aggregate Functions Ignore NULL

avg(CASE WHEN side = 'buy' THEN price END)
  • avg() calculates average of non-NULL values only
  • Only includes price when side is 'buy'
  • Automatically skips all other rows