Home > Software engineering >  BigQuery average column by condition
BigQuery average column by condition

Time:03-19

Assume I have the following simplified data in BigQuery:

WITH sales_log AS
 (
  SELECT 'John' as employee, 'ABC' client, 1234.56 sales, "phone" sale_type UNION ALL
  SELECT 'John' as employee, 'ABC' client, 9857.56 sales, "online" sale_type UNION ALL
  SELECT 'John' as employee, 'XYZ' client, 5678.56 sales, "phone" sale_type UNION ALL
  SELECT 'John' as employee, 'XYZ' client, 64875.25 sales, "online" sale_type UNION ALL
  SELECT 'Mary' as employee, 'ABC' client, 456.58 sales, "phone" sale_type UNION ALL
  SELECT 'Mary' as employee, 'ABC' client, 11585.58 sales, "online" sale_type UNION ALL
  SELECT 'Mary' as employee, 'XYZ' client, 4578.52 sales, "phone" sale_type UNION ALL
  SELECT 'Mary' as employee, 'XYZ' client, 56853.45 sales, "online" sale_type
  )
SELECT employee, AVG(sales) AS avg_sales
FROM sales_log
GROUP BY employee

I can easily get the average of the employees' sales.

Is there an easy way to also get the average of EACH TYPE of sale in a single row? So that the output would be like:

employee avg_sales avg_phone_sales avg_online_sales
John 20411.4825 3456.56 37366.405
Mary 18368.5325 2517.55 34219.515

Thank you in advance.

CodePudding user response:

Couple approaches:

  • DEMO's at bottom:
  • If the Types are limited you can use case expressions for each column.
  • If they are "Dynamic" then you need a dynamic pivot. (Several online examples exist; but this means dynamic SQL which can be prone to SQL injection)
  • NOTE: Typically data formatting such as this is done in the UI not the SQL.
  • NOTE: Use of Null ensures the "blank" values don't impact your average.

.

WITH sales_log AS
 (
  SELECT 'John' as employee, 'ABC' client, 1234.56 sales, 'phone' sale_type UNION ALL
  SELECT 'John' as employee, 'ABC' client, 9857.56 sales, 'online' sale_type UNION ALL
  SELECT 'John' as employee, 'XYZ' client, 5678.56 sales, 'phone' sale_type UNION ALL
  SELECT 'John' as employee, 'XYZ' client, 64875.25 sales, 'online' sale_type UNION ALL
  SELECT 'Mary' as employee, 'ABC' client, 456.58 sales, 'phone' sale_type UNION ALL
  SELECT 'Mary' as employee, 'ABC' client, 11585.58 sales, 'online' sale_type UNION ALL
  SELECT 'Mary' as employee, 'XYZ' client, 4578.52 sales, 'phone' sale_type UNION ALL
  SELECT 'Mary' as employee, 'XYZ' client, 56853.45 sales, 'online' sale_type
  )
SELECT employee, AVG(sales) AS avg_sales, 
       AVG(case when sale_type = 'phone' then sales else NULL end) as AVG_PhoneSales, 
       AVG(case when sale_type = 'online' then sales else NULL end) as AVG_OnLineSales
FROM sales_log
GROUP BY employee

GIVING US:

 ---------- -------------------- ----------------------- -------------------- 
| employee |     avg_sales      |  AVG_phonesales       | AVG_onlinesales    |
 ---------- -------------------- ----------------------- -------------------- 
| Mary     | 18368.532500000000 | 2517.5500000000000000 | 34219.515000000000 |
| John     | 20411.482500000000 | 3456.5600000000000000 | 37366.405000000000 |
 ---------- -------------------- ----------------------- -------------------- 

enter image description here

  • Related