BigQuery: скалярный подзапрос произвел более одного - агрегирование даты и времени в массив за промежуток времени - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь найти события, произошедшие за указанный c интервал времени (разные интервалы в строке), и добавить его в виде столбца. Две таблицы, прикрепленные в конце: (1) временные интервалы, (2) события даты и времени

Во-первых, я добавил столбец со всеми событиями времени данных в виде массива для каждой строки. пример

Во-вторых, я использовал этот код для подсчета количества даты и времени в каждом интервале:

-- count how many urine-output chart-events for every hourly interval
SELECT T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH,
sum((SELECT count(*) FROM UNNEST(twi.ca) as x WHERE x BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH)) NUMBER_OF_OUTPUTS_IN_INTERVAL
FROM TIMES_WITH_INTERVALS twi
group by T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH

Когда я пытался добавить еще один столбец с датой и временем в интервал (в массиве) я получаю:

Скалярный подзапрос произвел более одного элемента

Это код, который я использовал:

SELECT T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH,
sum((SELECT count(*) FROM UNNEST(twi.ca) as x WHERE x BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH)) NUMBER_OF_OUTPUTS_IN_INTERVAL,
ARRAY_AGG(FORMAT("%T",(SELECT * FROM UNNEST(twi.ca) as x WHERE x BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH))) AS ARRAY_OF_TIMES_IN_INTERVALL
FROM TIMES_WITH_INTERVALS twi
group by T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH

БОЛЬШОЕ ИЗОБРАЖЕНИЕ

У меня есть таблица (рисунок 2 в конце), на которой есть отметка даты и времени + измерение объема. Я хочу объединить значения, которые были измерены, в округленный интервал времени, что означает возможность выполнять арифметику c с измерениями каждого события.

Я открыт для другого подхода.

Расчет, который я хочу сделать - сумма:

  1. Для первого события измерения в интервале времени: проверьте разницу во времени с отметкой даты и времени предыдущего измерения в исходной таблице (в минутах), разделите значение на разницу во времени, умножьте его на разницу во времени с начала интервала.
  2. Все другие события измерения во временном интервале: просто добавьте их к сумме.
  3. Первое измерение после интервала: те же логики c первого измерения, но добавление к сумме части дополнения.

Ультимативное решение для меня

Благодаря огромной помощи Гордона Линоффа я смог правильно выполнить свой код. Когда я продолжал работать над «большими картинками», мне нужно было решение с большей вариабельностью для невыполненного арра - в итоге мы сочетаем решение Гордона Линоффа с CASE:

SELECT *,
      COUNT(case when x BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH then uo.charttime end) AS NUMBER_OF_OUTPUTS_IN_INTERVAL,
      ARRAY_AGG(case when x BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH then uo.charttime end IGNORE NULLS) AS ARRAY_OF_TIMES_IN_INTERVALL,
      ARRAY_AGG(case when x BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH then uo.value end IGNORE NULLS) AS ARRAY_OF_UO,
      ARRAY_REVERSE(ARRAY_AGG(case when x <= twi.TIME_INTERVAL_STARTS then x end IGNORE NULLS))[OFFSET(0)] AS TIME_BEFORE,
      ARRAY_AGG(case when x > twi.TIME_INTERVAL_FINISH then x end IGNORE NULLS)[OFFSET(0)] AS TIME_AFTER,
      ARRAY_AGG(case when x > twi.TIME_INTERVAL_FINISH then uo.value end IGNORE NULLS)[OFFSET(0)] AS UO_AFTER,
FROM TIMES_WITH_INTERVALS twi 
      LEFT JOIN UNNEST(twi.ca) x
      ON true
      LEFT JOIN uo
      ON uo.charttime = x
GROUP BY T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH
ORDER BY T_PLUS

скриншоты оригинальных таблиц:

  1. интервалы времени
  2. дата-время

1 Ответ

1 голос
/ 06 апреля 2020

Поместите format() и array_agg() в подзапрос:

(SELECT ARRAY_AGG(FORMAT('%T', x))
 FROM 
 WHERE x BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH
) AS ARRAY_OF_TIMES_IN_INTERVAL

Тем не менее, мне совершенно неясно, почему вы превращаете метку времени в строку для хранения в массиве. Вы можете просто иметь массив собственного типа.

РЕДАКТИРОВАТЬ:

Ваш запрос должен выглядеть примерно так:

SELECT T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH,
       COUNT(x) as cnt,
       ARRAY_AGG(x) as timestamps
FROM TIMES_WITH_INTERVALS twi LEFT JOIN
     UNNEST(twi.ca) x
     ON x BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH
GROUP BY T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...