Количество 3 различных значений по стране объединение

# #sql #google-bigquery

Вопрос:

Я пытаюсь выяснить, как подсчитать, сколько клиентов находится в каждом статусе по стране.

Я начал с объединения двух таблиц customers_customers и customer_status получения значений страны для каждого клиента. Это даст мне одноразовый ответ для конкретной страны и статуса. Однако я не могу понять, как подсчитать, сколько клиентов (по странам) находится в каждом статусе. (Пример желаемого результата ниже)

 SELECT COUNT (customers_customers.customerID)
FROM customers_customers
LEFT JOIN customer_status
ON customers_customers.customerID = customer_status.customerID
WHERE customers_customers.Country = "US" and customer_status.status = "In Progress";
 

customers_customers

CustomerID Страна
1 США
2 CA
3 Великобритания
4 ГБ
5 США

customer_status

CustomerID Статус
1 Выполняется
2 Выполнено
3 Не запущен
4 Выполнено
5 Выполняется

В конечном счете, я ищу этот результат:

Страна Не запущен Выполняется Выполнено
США 2 3 1
Великобритания 1 6 2
ГБ 2 5 1
CA 2 1 7

Ответ №1:

Вы можете использовать агрегатную функцию SUM by condition и group by country .

 SELECT
  country,
  SUM(CASE WHEN cs.status = 'Not Started' THEN 1 ELSE 0 END) AS NotStarted,
  SUM(CASE WHEN cs.status = 'In Progress' THEN 1 ELSE 0 END) AS InProgress,
  SUM(CASE WHEN cs.status = 'Done' THEN 1 ELSE 0 END) AS Done
FROM customers_customers cc
JOIN customer_status cs ON cc.customerID = cs.customerID
GROUP BY country
 

db<>скрипка

Комментарии:

1. Или вы можете использовать COUNT(*) FILTER (WHERE cs.status = 'Not Started') вместо SUM(...) .

2. В итоге я использовал SUM (СЛУЧАЙ, КОГДА …), И это сработало! Я попытался использовать ФИЛЬТР COUNT (*), и когда я продолжал натыкаться на стену, я прочитал, что он не работает с Google BQ, который я использую. Спасибо за помощь!

3. Вы получили это! 🙂 Учимся пользоваться этим сайтом, ха-ха

Ответ №2:

dbfiddle

 select
  cc.country as "Country",
  count(*) filter (where cs.status = 'Not Started') as "Not Started",
  count(*) filter (where cs.status = 'In Progress') as "In Progress",
  count(*) filter (where cs.status = 'Done') as "Done"
from 
  customers_customers cc left join customer_status cs
    on cc."customerID" = cs."customerID"
group by 1
 

Ответ №3:

Рассмотрим ниже довольно общий подход

 select * from (
  select * replace(replace(status, ' ', '_') as status)
  from customers_customers
  join customer_status
  using (customerID)
)
pivot (count(customerID) for status in ('Not_Started', 'In_Progress', 'Done'))         
 

если применяется к образцу / фиктивным данным в вашем вопросе — вывод

введите описание изображения здесь