как сложить несколько счетов на разных таблицах и разных фильтрах - PullRequest
0 голосов
/ 03 февраля 2020

Я хочу получить box_id, date, hour и sum нескольких count id в другой таблице с различными status в каждой таблице, но с одинаковыми box_id,

пример

table 1
(filter by status = finished)


id   box_id              date                status
i     20      2019-01-01 01:00:00.000 UTC    finished
2     21      2019-01-01 02:00:00.000 UTC    finished
3     21      2019-01-01 01:00:00.000 UTC    unfinished


table 2
(filter by status = start)

id   box_id              date                status
i     21      2019-01-01 01:00:00.000 UTC    start
2     22      2019-01-01 02:00:00.000 UTC    end
3     23      2019-01-01 01:00:00.000 UTC    start
4     24      2019-01-01 01:00:00.000 UTC    start


table 3
(filter by status = close)


id   box_id              date                status
i     21      2019-01-01 03:00:00.000 UTC    close
2     22      2019-01-01 02:00:00.000 UTC    end
3     24      2019-01-01 01:00:00.000 UTC    close

result that i want:

box_id      date        hour       count
20         2019-01-01     1          1
21         2019-01-01     1          1
21         2019-01-01     2          1
21         2019-01-01     3          1
23         2019-01-01     1          1
24         2019-01-01     1          2

это мой запрос, который работает для таблицы 1: как я могу получить для всех в 1 таблице?

select box_id, 
date(date_update), 
EXTRACT(hour FROM date_update) as hourly, 
count(id)
from table1
where status = "finished"
group by box_id, date(date_update), EXTRACT(hour FROM date_update)

формат час = 0 - 23

Ответы [ 2 ]

1 голос
/ 04 февраля 2020

Предполагая, что ваше поле date относится к типу данных TIMESTAMP - ниже для стандарта BigQuery SQL

#standardSQL
SELECT box_id, date, hour, COUNT(1) cnt
FROM (
  SELECT box_id, DATE(date) date, EXTRACT(HOUR FROM date) hour 
  FROM `project.dataset.table1` WHERE status = 'finished' UNION ALL
  SELECT box_id, DATE(date) date, EXTRACT(HOUR FROM date) hour 
  FROM `project.dataset.table2` WHERE status = 'start' UNION ALL
  SELECT box_id, DATE(date) date, EXTRACT(HOUR FROM date) hour 
  FROM `project.dataset.table3` WHERE status = 'close'
)
GROUP BY box_id, date, hour

Вы можете протестировать, поиграть с выше, используя данные образца / фиктивного файла из вашего вопроса, как показано ниже пример

#standardSQL
WITH `project.dataset.table1` AS (
  SELECT 1 id, 20 box_id, TIMESTAMP '2019-01-01 01:00:00.000 UTC'date, 'finished' status UNION ALL
  SELECT 2, 21, '2019-01-01 02:00:00.000 UTC', 'finished' UNION ALL
  SELECT 3, 21, '2019-01-01 01:00:00.000 UTC', 'unfinished' 
), `project.dataset.table2` AS (
  SELECT 1 id, 21 box_id, TIMESTAMP '2019-01-01 01:00:00.000 UTC' date, 'start' status UNION ALL
  SELECT 2, 22, '2019-01-01 02:00:00.000 UTC', 'end' UNION ALL
  SELECT 3, 23, '2019-01-01 01:00:00.000 UTC', 'start' UNION ALL
  SELECT 4, 24, '2019-01-01 01:00:00.000 UTC', 'start' 
), `project.dataset.table3` AS (
  SELECT 1 id, 21 box_id, TIMESTAMP '2019-01-01 03:00:00.000 UTC' date, 'close' status UNION ALL
  SELECT 2, 22, '2019-01-01 02:00:00.000 UTC', 'end' UNION ALL
  SELECT 3, 24, '2019-01-01 01:00:00.000 UTC', 'close' 
)
SELECT box_id, date, hour, COUNT(1) cnt
FROM (
  SELECT box_id, DATE(date) date, EXTRACT(HOUR FROM date) hour 
  FROM `project.dataset.table1` WHERE status = 'finished' UNION ALL
  SELECT box_id, DATE(date) date, EXTRACT(HOUR FROM date) hour 
  FROM `project.dataset.table2` WHERE status = 'start' UNION ALL
  SELECT box_id, DATE(date) date, EXTRACT(HOUR FROM date) hour 
  FROM `project.dataset.table3` WHERE status = 'close'
)
GROUP BY box_id, date, hour
-- ORDER BY box_id, date, hour   

с результатом

Row box_id  date        hour    cnt  
1   20      2019-01-01  1       1    
2   21      2019-01-01  1       1    
3   21      2019-01-01  2       1    
4   21      2019-01-01  3       1    
5   23      2019-01-01  1       1    
6   24      2019-01-01  1       2      

Ниже приведены слегка реорганизованные версии (очевидно, с одинаковым выводом)

#standardSQL
SELECT box_id, DATE(date) date, EXTRACT(HOUR FROM date) hour, 
  COUNTIF(
    (t = 1 AND status = 'finished') OR
    (t = 2 AND status = 'start') OR
    (t = 3 AND status = 'close') 
  ) cnt
FROM (
  SELECT 1 t, * FROM `project.dataset.table1` UNION ALL
  SELECT 2, * FROM `project.dataset.table2` UNION ALL
  SELECT 3, * FROM `project.dataset.table3` 
)
GROUP BY box_id, date, hour
HAVING cnt > 0

ИЛИ

#standardSQL
SELECT box_id, DATE(date) date, EXTRACT(HOUR FROM date) hour, COUNT(1) cnt
FROM (
  SELECT * FROM `project.dataset.table1` WHERE status = 'finished' UNION ALL
  SELECT * FROM `project.dataset.table2` WHERE status = 'start' UNION ALL
  SELECT * FROM `project.dataset.table3` WHERE status = 'close'
)
GROUP BY box_id, date, hour
0 голосов
/ 03 февраля 2020

Как обсуждалось в комментариях, поскольку вы хотите добавить поля из нескольких таблиц, я рекомендую использовать JOIN . Существует несколько типов JOIN , в случае если все таблицы имеют одинаковое количество и значения для box_id , вы можете использовать INNER JOIN . Однако, если это не так, и вы все еще хотите увидеть счетчик для каждого box_id , хотя этот box_id может отсутствовать во всех трех таблицах, которые я предлагаю вам использовать FULL JOIN .

Ниже я написал упрощенный пример, в котором я использовал FULL JOIN вместе с другими встроенными функциями в BigQuery.

    SELECT DISTINCT
      coalesce(t1.box_id, t2.box_id, t3.box_id) AS id,
      (ifnull(t1.count,0)+ifnull(t2.count,0)+ifnull(t3.count,0)) AS count
    FROM (
      SELECT
        box_id,
        count(box_id) AS count
      FROM
        `source_table1`
      WHERE status = 'finished'
      GROUP BY
        box_id) t1
    FULL JOIN (
      SELECT
        box_id,
        count (box_id) AS count
      FROM
        `source_table2`
      WHERE status = 'finished'
      GROUP BY
        box_id ) t2
    ON
      t1.box_id=t2.box_id
    FULL JOIN (
      SELECT
        box_id,
        count (box_id) AS count
      FROM
        `source_table3`
      WHERE status = 'finished'
      GROUP BY
        box_id) AS t3
    ON
      t1.box_id=t3.box_id
    WHERE
      t1.box_id IS NOT NULL
      OR t2.box_id IS NOT NULL
      OR t3.box_id IS NOT NULL
    ORDER BY
      id

Обратите внимание, что я использовал COALESCE , чтобы выбрать box_id , если это поле не существует в таблице 1, оно будет перемещено в таблицу 2 и т. Д. , Впоследствии я использовал IFNULL для суммирования результата подсчета, встречающегося в каждой таблице, этот метод использовался, чтобы убедиться, что счетчик установлен в ноль, когда box_id отсутствует в таблице. , Наконец, я использовал предложение WHERE , чтобы при подсчете учитывалось условие, которое вы наложили.

Я использовал приведенные ниже примеры данных для воспроизведения вашего случая:

Таблица 1:

enter image description here

Таблица 2 и Таблица 3:

enter image description here

Следовательно, вывод был:

enter image description here

Надеюсь, это поможет.

...