Bigquery: циклы и вставка - PullRequest
       10

Bigquery: циклы и вставка

0 голосов
/ 08 апреля 2020
  1. Я написал запрос, который получает целое число в объявленной переменной («Patient_id» вверху) и создает таблицу выходных данных для этого идентификатора.
  2. У меня есть таблица идентификаторов пациентов, которую я хочу повторить с запросом выше ('ICUSTAY_IDs').
  3. Я создал пустую таблицу со столбцами, которые соответствуют запросу выше ('AllUrineOutputsAdjusted) ').
  4. LASTLY - Я хочу повторить (или l oop) запрос из шага 1 по значениям в таблице из шага 2 и вставить его в пустую таблицу по адресу шаг 3.

Мой набор данных:

  • mimi c -iii-256413
    • Таблицы
      • AllUrineOutputs (необработанные данные)
      • AllUrineOutputsAdjusted (целевая таблица
      • ICUSTAY_IDs (список идентификаторов для l oop)

Мой запрос с первого шага (входная переменная вверху):

-- only variable you should input (ICUSTAY_ID)
DECLARE patient_id INT64 DEFAULT 230514;

WITH uo AS (
-- relevant urine-ouput columns with CIS for specific icustay_id
  SELECT ICUSTAY_ID, CHARTTIME, VALUE,
  If(oe.itemid < 50000, "CareVue", "MetaVision") as CIS
  FROM `mimic-iii-256413.Tables.AllUrineOutputs` oe
    where oe.ICUSTAY_ID  in (patient_id)
  ORDER BY charttime asc
), 
RAW_ARRAY_OF_TIMES AS (
-- array of numbers that represent total hours measured for specific icustay_id + start-time rounded up
  SELECT GENERATE_ARRAY(1, DATETIME_DIFF(max(uo.charttime), min(uo.charttime), hour), 1) ary, 
  DATETIME_TRUNC(min(uo.charttime), HOUR)  start_time_rounded_up
  FROM uo
),
LISTED_ARRAY_OF_TIMES AS (
SELECT * FROM RAW_ARRAY_OF_TIMES CROSS JOIN UNNEST(ary) as T_PLUS
),
TIMES_WITH_INTERVALS AS (
-- total hours list + absolute time intervals + uo.charttime array for every row
SELECT T_PLUS, START_TIME_ROUNDED_UP,
DATETIME_ADD(start_time_rounded_up, INTERVAL T_PLUS HOUR) as TIME_INTERVAL_STARTS,
DATETIME_ADD(start_time_rounded_up, INTERVAL T_PLUS + 1 HOUR) as TIME_INTERVAL_FINISH,
ARRAY(SELECT charttime FROM uo) AS ca,
ARRAY(SELECT charttime FROM uo) AS ca2,
ARRAY(SELECT charttime FROM uo) AS ca3
FROM LISTED_ARRAY_OF_TIMES
),
INTERVALS_WITH_TIMES_AND_UO AS (
-- count how many urine-output chart-events for every hourly interval, specify datetime. 
-- also adds last datetime event before the interval + first event after: datetime and value
---- ALL THE MINIMAL NEEDS FOR THE ADJUSTED CALCULATION IS PRESENT. ----
SELECT T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH,
      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
),
CALCULATION_BOARD1 AS (
-- calculations step 1
SELECT T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH, NUMBER_OF_OUTPUTS_IN_INTERVAL, ARRAY_OF_TIMES_IN_INTERVALL, ARRAY_OF_UO,
  IFNULL((SELECT SUM(s) FROM UNNEST(ARRAY_OF_UO) s), (0)) SIMPLE_SUM,
  TIME_BEFORE,
  IFNULL((DATETIME_DIFF(ARRAY_OF_TIMES_IN_INTERVALL[OFFSET(0)], TIME_INTERVAL_STARTS, minute)), (0)) MINUTES_BEFORE_INTERVAL,
  IFNULL((DATETIME_DIFF(ARRAY_OF_TIMES_IN_INTERVALL[OFFSET(0)], TIME_BEFORE, minute)), (0)) MINUTES_BEFORE_TOTAL,
  TIME_AFTER,
  UO_AFTER,
  IFNULL((DATETIME_DIFF(TIME_INTERVAL_FINISH, ARRAY_REVERSE(ARRAY_OF_TIMES_IN_INTERVALL)[OFFSET(0)], minute)), (60)) MINUTES_AFTER_INTERVAL,
  IFNULL((DATETIME_DIFF(TIME_AFTER, ARRAY_REVERSE(ARRAY_OF_TIMES_IN_INTERVALL)[OFFSET(0)], minute)), (
    DATETIME_DIFF(TIME_AFTER, TIME_BEFORE, minute))
  ) MINUTES_AFTER_TOTAL,
FROM INTERVALS_WITH_TIMES_AND_UO
),
CALCULATION_BOARD2 AS (
-- calculations step 2
select *,
  (CASE WHEN (MINUTES_BEFORE_TOTAL IS NULL) OR (MINUTES_BEFORE_TOTAL = 0) THEN 0 ELSE 
    MINUTES_BEFORE_INTERVAL / MINUTES_BEFORE_TOTAL
  END) FIRST_UO_PORTION,
  (CASE WHEN (MINUTES_AFTER_TOTAL IS NULL) OR (MINUTES_AFTER_TOTAL = 0) THEN 0 ELSE 
    MINUTES_AFTER_INTERVAL / MINUTES_AFTER_TOTAL
  END) AFTER_UO_PORTION
FROM CALCULATION_BOARD1
),
FINAL_CALC AS (
-- calculations step 3 (FINAL)
-- all the steps for all the calculation present for quality check
SELECT *,
  CAST(
    (IFNULL((SELECT SUM(s) FROM UNNEST(ARRAY_OF_UO) s), (0))) - (IFNULL((ARRAY_OF_UO[OFFSET(0)]), (0))) +
    ((IFNULL((ARRAY_OF_UO[OFFSET(0)]), (0))) * FIRST_UO_PORTION) +
    (UO_AFTER * AFTER_UO_PORTION)
  AS INT64) ADJUSTED_SUM
FROM CALCULATION_BOARD2
),
SUMMARY AS (
-- minimal summary
SELECT patient_id, T_PLUS, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH, SIMPLE_SUM, ADJUSTED_SUM
FROM FINAL_CALC
ORDER BY T_PLUS)



SELECT * FROM SUMMARY

Это текущий результат из запрос. Я хочу, чтобы каждый l oop был вставлен в таблицу 'AllUrineOutputsAdjusted'.


ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ

Благодаря ответу Саба, я получил правильный ужас ction:

Вместо использования циклов я бы использовал идентификатор пациента в группе для сводок. Таким образом, вы можете запускать свои сводки без всяких oop.

Это мой последний запрос, и я сохранил его в новой таблице с консолью GUI (также можно выполнить «вставить» «). Код Sab, вероятно, более эффективен и элегантен, мое решение лучше подходит для отладки:

WITH uo AS (
-- relevant urine-ouput columns
  SELECT ICUSTAY_ID, CHARTTIME, VALUE, 
  --   CIS method
   If(oe.itemid < 50000, "CareVue", "MetaVision") as CIS
  FROM `mimic-iii-256413.Tables.AllUrineOutputs` oe
    WHERE oe.ICUSTAY_ID  in (SELECT ICUSTAY_ID FROM `Tables.ICUSTAY_IDs`)
  GROUP BY ICUSTAY_ID, CHARTTIME, VALUE, oe.itemid
  ORDER BY ICUSTAY_ID, charttime asc
), 
RAW_ARRAY_OF_TIMES AS (
-- array of numbers that represent total hours measured for specific icustay_id + start-time rounded up
  SELECT ICUSTAY_ID, GENERATE_ARRAY(1, DATETIME_DIFF(max(uo.charttime), min(uo.charttime), hour), 1) ary, 
    DATETIME_TRUNC(min(uo.charttime), HOUR)  start_time_rounded_up
  FROM uo
  GROUP BY ICUSTAY_ID
),
LISTED_ARRAY_OF_TIMES AS (
  SELECT * FROM RAW_ARRAY_OF_TIMES CROSS JOIN UNNEST(ary) as T_PLUS
  ORDER BY ICUSTAY_ID, T_PLUS
),
TIMES_WITH_INTERVALS AS (
-- total hours list + absolute time intervals
  SELECT laot.ICUSTAY_ID, laot.T_PLUS, laot.START_TIME_ROUNDED_UP,
    DATETIME_ADD(start_time_rounded_up, INTERVAL T_PLUS HOUR) as TIME_INTERVAL_STARTS,
    DATETIME_ADD(start_time_rounded_up, INTERVAL T_PLUS + 1 HOUR) as TIME_INTERVAL_FINISH,
  FROM LISTED_ARRAY_OF_TIMES laot
  GROUP BY laot.T_PLUS, laot.ICUSTAY_ID, laot.START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH
  ORDER BY laot.ICUSTAY_ID, laot.T_PLUS
),
INTERVALS_WITH_TIMES_AND_UO AS (
-- count how many urine-output chart-events for every hourly interval, specify datetime. 
-- also adds last datetime event before the interval + first event after: datetime and value
---- ALL THE MINIMAL NEEDS FOR THE ADJUSTED CALCULATION IS PRESENT. ----
  SELECT twi.ICUSTAY_ID, T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH,
    COUNT(case when (uo.charttime BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH) AND 
      (uo.ICUSTAY_ID = twi.ICUSTAY_ID) then uo.charttime end) 
      AS NUMBER_OF_OUTPUTS_IN_INTERVAL,
    ARRAY_AGG(case when (uo.charttime BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH) AND 
      (uo.ICUSTAY_ID = twi.ICUSTAY_ID) then uo.charttime end IGNORE NULLS ORDER BY uo.charttime)
      AS ARRAY_OF_TIMES_IN_INTERVALL,
    ARRAY_AGG(case when (uo.charttime BETWEEN twi.TIME_INTERVAL_STARTS AND twi.TIME_INTERVAL_FINISH) AND 
      (uo.ICUSTAY_ID = twi.ICUSTAY_ID) then uo.value end IGNORE NULLS ORDER BY uo.charttime) 
      AS ARRAY_OF_UO,
    ARRAY_REVERSE(ARRAY_AGG(case when (uo.charttime <= twi.TIME_INTERVAL_STARTS) AND 
      (uo.ICUSTAY_ID = twi.ICUSTAY_ID) then uo.charttime end IGNORE NULLS ORDER BY uo.charttime))[OFFSET(0)] 
      AS TIME_BEFORE,
    ARRAY_AGG(case when (uo.charttime > twi.TIME_INTERVAL_FINISH) AND 
      (uo.ICUSTAY_ID = twi.ICUSTAY_ID) then uo.charttime end IGNORE NULLS ORDER BY uo.charttime)[OFFSET(0)] 
      AS TIME_AFTER,
    ARRAY_AGG(case when (uo.charttime > twi.TIME_INTERVAL_FINISH) 
      AND (uo.ICUSTAY_ID = twi.ICUSTAY_ID) then uo.value end IGNORE NULLS ORDER BY uo.charttime)[OFFSET(0)] 
      AS UO_AFTER,
  FROM TIMES_WITH_INTERVALS twi 
    LEFT JOIN uo
    ON uo.ICUSTAY_ID = twi.ICUSTAY_ID
  GROUP BY twi.ICUSTAY_ID, T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH
  ORDER BY twi.ICUSTAY_ID, T_PLUS
),
CALCULATION_BOARD1 AS (
-- calculations step 1
  SELECT ICUSTAY_ID, T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH, NUMBER_OF_OUTPUTS_IN_INTERVAL, ARRAY_OF_TIMES_IN_INTERVALL, ARRAY_OF_UO,
    IFNULL((SELECT SUM(s) FROM UNNEST(ARRAY_OF_UO) s), (0)) SIMPLE_SUM,
    TIME_BEFORE,
    IFNULL((DATETIME_DIFF(ARRAY_OF_TIMES_IN_INTERVALL[OFFSET(0)], TIME_INTERVAL_STARTS, minute)), (0)) MINUTES_BEFORE_INTERVAL,
    IFNULL((DATETIME_DIFF(ARRAY_OF_TIMES_IN_INTERVALL[OFFSET(0)], TIME_BEFORE, minute)), (null)) MINUTES_BEFORE_TOTAL,
    TIME_AFTER,
    UO_AFTER,
    IFNULL((DATETIME_DIFF(TIME_INTERVAL_FINISH, ARRAY_REVERSE(ARRAY_OF_TIMES_IN_INTERVALL)[OFFSET(0)], minute)), (60)) MINUTES_AFTER_INTERVAL,
    IFNULL((DATETIME_DIFF(TIME_AFTER, ARRAY_REVERSE(ARRAY_OF_TIMES_IN_INTERVALL)[OFFSET(0)], minute)), (
      DATETIME_DIFF(TIME_AFTER, TIME_BEFORE, minute))
    ) MINUTES_AFTER_TOTAL,
  FROM INTERVALS_WITH_TIMES_AND_UO
  ORDER BY ICUSTAY_ID, T_PLUS
),
CALCULATION_BOARD2 AS (
-- calculations step 2
  SELECT *,
    (CASE WHEN (MINUTES_BEFORE_TOTAL IS NULL) OR (MINUTES_BEFORE_TOTAL = 0) THEN 0 ELSE 
      MINUTES_BEFORE_INTERVAL / MINUTES_BEFORE_TOTAL
    END) FIRST_UO_PORTION,
    (CASE WHEN (MINUTES_AFTER_TOTAL IS NULL) OR (MINUTES_AFTER_TOTAL = 0) THEN 0 ELSE 
      MINUTES_AFTER_INTERVAL / MINUTES_AFTER_TOTAL
    END) AFTER_UO_PORTION
  FROM CALCULATION_BOARD1
  ORDER BY ICUSTAY_ID, T_PLUS
),
FINAL_CALC AS (
-- calculations step 3 (FINAL)
-- all the steps for all the calculation present for quality chck
  SELECT *,
    CAST(
      IF (((NUMBER_OF_OUTPUTS_IN_INTERVAL = 0) AND (((MINUTES_BEFORE_TOTAL IS NULL) OR (MINUTES_BEFORE_TOTAL > 120)) AND ((MINUTES_AFTER_TOTAL IS NULL) OR (MINUTES_AFTER_TOTAL > 240)))),
      NULL,    
        (IFNULL((SELECT SUM(s) FROM UNNEST(ARRAY_OF_UO) s), (0))) - (IFNULL((ARRAY_OF_UO[OFFSET(0)]), (0))) +
        ((IFNULL((ARRAY_OF_UO[OFFSET(0)]), (0))) * (IFNULL(FIRST_UO_PORTION, 0))) +
        ((IFNULL(UO_AFTER, 0)) * (IFNULL(AFTER_UO_PORTION, 0)))
      )
    AS INT64) ADJUSTED_SUM
  FROM CALCULATION_BOARD2
  ORDER BY ICUSTAY_ID, T_PLUS
),
SUMMARY AS (
-- minimal summary
  SELECT ICUSTAY_ID, T_PLUS, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH, SIMPLE_SUM, ADJUSTED_SUM
  FROM FINAL_CALC
  ORDER BY ICUSTAY_ID, T_PLUS
)

SELECT * FROM SUMMARY
ORDER BY ICUSTAY_ID, T_PLUS

1 Ответ

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

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

Поскольку я не знаю о вашей входной таблице, я создал фиктивную таблицу с именем rawdata. Исходя из необработанных данных, вы можете увидеть мой запрос ниже.

По сути, я создал массив идентификаторов пациентов и добавил терпение в группу по столбцам.

Во время рефакторинга кода я удалил некоторые избыточные столбцы, такие как ca2, ca2, CIS, а также ненужные промежуточные таблицы и объединения. Его можно оптимизировать больше, но я хотел, чтобы он был похож на ваш, чтобы его было легче понять и отладить.

DECLARE patient_ids ARRAY<INT64> DEFAULT [1,2];

WITH 
rawdata AS (
  SELECT 1 as ICUSTAY_ID, CAST('2020-04-01 01:00:00' as datetime) as CHARTTIME, 100 as VALUE UNION ALL
  SELECT 1 as ICUSTAY_ID, CAST('2020-04-01 02:00:00' as datetime) as CHARTTIME, 110 as VALUE UNION ALL
  SELECT 1 as ICUSTAY_ID, CAST('2020-04-01 03:00:00' as datetime) as CHARTTIME, 120 as VALUE UNION ALL
  SELECT 1 as ICUSTAY_ID, CAST('2020-04-01 04:00:00' as datetime) as CHARTTIME, 130 as VALUE UNION ALL
  SELECT 1 as ICUSTAY_ID, CAST('2020-04-01 05:00:00' as datetime) as CHARTTIME, 140 as VALUE UNION ALL
  SELECT 1 as ICUSTAY_ID, CAST('2020-04-01 06:00:00' as datetime) as CHARTTIME, 150 as VALUE UNION ALL
  SELECT 2 as ICUSTAY_ID, CAST('2020-04-01 01:00:00' as datetime) as CHARTTIME, 200 as VALUE UNION ALL
  SELECT 2 as ICUSTAY_ID, CAST('2020-04-01 02:00:00' as datetime) as CHARTTIME, 210 as VALUE UNION ALL
  SELECT 2 as ICUSTAY_ID, CAST('2020-04-01 03:00:00' as datetime) as CHARTTIME, 220 as VALUE UNION ALL
  SELECT 2 as ICUSTAY_ID, CAST('2020-04-01 04:00:00' as datetime) as CHARTTIME, 230 as VALUE UNION ALL
  SELECT 2 as ICUSTAY_ID, CAST('2020-04-01 05:00:00' as datetime) as CHARTTIME, 240 as VALUE UNION ALL
  SELECT 2 as ICUSTAY_ID, CAST('2020-04-01 06:00:00' as datetime) as CHARTTIME, 250 as VALUE
),
uo AS (
-- relevant urine-ouput columns with CIS for specific icustay_id
  SELECT 
      ICUSTAY_ID as patientid, 
      DATETIME_TRUNC(MIN(CHARTTIME), HOUR) as start_time_rounded_up,
      GENERATE_ARRAY(1, DATETIME_DIFF(MAX(CHARTTIME), MIN(CHARTTIME), hour), 1) as T_PLUS_arr,
      ARRAY_AGG(STRUCT(CHARTTIME, VALUE)) as chart_values
  FROM rawdata oe
  WHERE oe.ICUSTAY_ID in UNNEST(patient_ids)
  GROUP BY 1
),
TIMES_WITH_INTERVALS AS (
  -- total hours list + absolute time intervals + uo.charttime array for every row
  SELECT 
    patientid,
    T_PLUS, START_TIME_ROUNDED_UP,
    DATETIME_ADD(start_time_rounded_up, INTERVAL T_PLUS HOUR) as TIME_INTERVAL_STARTS,
    DATETIME_ADD(start_time_rounded_up, INTERVAL T_PLUS + 1 HOUR) as TIME_INTERVAL_FINISH,
    chart_values
  FROM uo
  JOIN UNNEST(T_PLUS_arr) as T_PLUS
)
,
INTERVALS_WITH_TIMES_AND_UO AS (
  -- count how many urine-output chart-events for every hourly interval, specify datetime. 
  -- also adds last datetime event before the interval + first event after: datetime and value
  ---- ALL THE MINIMAL NEEDS FOR THE ADJUSTED CALCULATION IS PRESENT. ----
  SELECT 
      patientid, T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH,
      (SELECT COUNT(*) FROM UNNEST(chart_values) WHERE charttime BETWEEN TIME_INTERVAL_STARTS AND TIME_INTERVAL_FINISH) AS NUMBER_OF_OUTPUTS_IN_INTERVAL,
      (SELECT ARRAY_AGG(charttime) FROM UNNEST(chart_values) WHERE charttime BETWEEN TIME_INTERVAL_STARTS AND TIME_INTERVAL_FINISH) AS ARRAY_OF_TIMES_IN_INTERVALL,
      (SELECT ARRAY_AGG(value) FROM UNNEST(chart_values) WHERE charttime BETWEEN TIME_INTERVAL_STARTS AND TIME_INTERVAL_FINISH) AS ARRAY_OF_UO,
      (SELECT charttime FROM UNNEST(chart_values) WHERE charttime <= TIME_INTERVAL_STARTS ORDER BY charttime DESC LIMIT 1 ) AS TIME_BEFORE,
      (SELECT charttime FROM UNNEST(chart_values) WHERE charttime > twi.TIME_INTERVAL_FINISH ORDER BY charttime LIMIT 1 ) AS TIME_AFTER,
      (SELECT value FROM UNNEST(chart_values) WHERE charttime > twi.TIME_INTERVAL_FINISH ORDER BY charttime LIMIT 1 ) AS UO_AFTER
  FROM TIMES_WITH_INTERVALS twi
  ORDER BY patientid, T_PLUS
),
CALCULATION_BOARD1 AS (
  -- calculations step 1
  SELECT 
    patientid, T_PLUS, START_TIME_ROUNDED_UP, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH, NUMBER_OF_OUTPUTS_IN_INTERVAL, ARRAY_OF_TIMES_IN_INTERVALL, ARRAY_OF_UO,
    IFNULL((SELECT SUM(s) FROM UNNEST(ARRAY_OF_UO) s), (0)) SIMPLE_SUM,
    TIME_BEFORE,
    IFNULL((DATETIME_DIFF(ARRAY_OF_TIMES_IN_INTERVALL[OFFSET(0)], TIME_INTERVAL_STARTS, minute)), (0)) MINUTES_BEFORE_INTERVAL,
    IFNULL((DATETIME_DIFF(ARRAY_OF_TIMES_IN_INTERVALL[OFFSET(0)], TIME_BEFORE, minute)), (0)) MINUTES_BEFORE_TOTAL,
    TIME_AFTER,
    UO_AFTER,
    IFNULL((DATETIME_DIFF(TIME_INTERVAL_FINISH, ARRAY_REVERSE(ARRAY_OF_TIMES_IN_INTERVALL)[OFFSET(0)], minute)), (60)) MINUTES_AFTER_INTERVAL,
    IFNULL((DATETIME_DIFF(TIME_AFTER, ARRAY_REVERSE(ARRAY_OF_TIMES_IN_INTERVALL)[OFFSET(0)], minute)), (
      DATETIME_DIFF(TIME_AFTER, TIME_BEFORE, minute))
    ) MINUTES_AFTER_TOTAL,
  FROM INTERVALS_WITH_TIMES_AND_UO
),
CALCULATION_BOARD2 AS (
  -- calculations step 2
  select *,
    (CASE WHEN (MINUTES_BEFORE_TOTAL IS NULL) OR (MINUTES_BEFORE_TOTAL = 0) THEN 0 ELSE 
      MINUTES_BEFORE_INTERVAL / MINUTES_BEFORE_TOTAL
    END) FIRST_UO_PORTION,
    (CASE WHEN (MINUTES_AFTER_TOTAL IS NULL) OR (MINUTES_AFTER_TOTAL = 0) THEN 0 ELSE 
      MINUTES_AFTER_INTERVAL / MINUTES_AFTER_TOTAL
    END) AFTER_UO_PORTION
  FROM CALCULATION_BOARD1
),
FINAL_CALC AS (
  -- calculations step 3 (FINAL)
  -- all the steps for all the calculation present for quality check
  SELECT *,
    CAST(
      (IFNULL((SELECT SUM(s) FROM UNNEST(ARRAY_OF_UO) s), (0))) - (IFNULL((ARRAY_OF_UO[OFFSET(0)]), (0))) +
      ((IFNULL((ARRAY_OF_UO[OFFSET(0)]), (0))) * FIRST_UO_PORTION) +
      (UO_AFTER * AFTER_UO_PORTION)
    AS INT64) ADJUSTED_SUM
  FROM CALCULATION_BOARD2
),
SUMMARY AS (
  -- minimal summary
  SELECT patientid, T_PLUS, TIME_INTERVAL_STARTS, TIME_INTERVAL_FINISH, SIMPLE_SUM, ADJUSTED_SUM
  FROM FINAL_CALC
  ORDER BY patientid, T_PLUS
)
SELECT * FROM SUMMARY
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...