Есть ли другое решение для расчета данных по отфильтрованной дате без предложения «с»? - PullRequest
0 голосов
/ 27 сентября 2019

Необходимо вычислить значение, когда дата

+------+------------+------------------+
| Name |    date    | order_id | value |
+------+------------+----------+-------+
| JONES| 2019-01-03 | 11       |    10 |
| JONES| 2019-01-05 | 12       |    5  |
| JONES| 2019-06-03 | 13       |    3  |
| JONES| 2019-07-03 | 14       |    20 |
| John | 2019-07-23 | 15       |    10 |
+------+------------+----------+-------+

Мое решение:

 WITH data AS (
      SELECT "JONES" name, DATE("2019-01-03") date_time, "11" order_id, 10 value
      UNION ALL
      SELECT "JONES", DATE("2019-01-05"), "12", 5
      UNION ALL
      SELECT "JONES", DATE("2019-06-03"), "13", 3
      UNION ALL
      SELECT "JONES", DATE("2019-07-03"), "14", 20
      UNION ALL
      SELECT "John", DATE("2019-07-23"), "15", 10
    ),
data2 AS (
    SELECT *, MIN(date_time) OVER (PARTITION BY name) min_date
    FROM data
)    
    SELECT name,
    ARRAY_AGG(STRUCT(order_id as f_id, date_time as f_date) ORDER BY order_id LIMIT 1)[OFFSET(0)].*,
    sum(case when date_time< date_add(min_date,interval 3 day) then value  end)  as total_value_day3,
    SUM(value) AS total
    FROM data2
    GROUP BY name

Вывод:

+------+------+------------+----------------+------+
| name | f_id | f_date     |total_value_day3| total|
+------+------+------------+----------------+------+
| JONES| 11   | 2019-01-03 | 15             | 38   | 
| John | 15   | 2019-07-23 | 10             | 10   | 
+------+------+------------+----------------+------+

Так что мой вопрос, можно ли рассчитать то же самое с более эффективнымпуть?Или это решение подходит для больших наборов данных?

1 Ответ

1 голос
/ 27 сентября 2019

Следующие результаты получают те же результаты без использования оконных функций или агрегации массивов, поэтому BQ должен делать меньше упорядочивания / разбиения.В этом небольшом примере мой запрос выполняется дольше, но меньше тасуется байтов.Если вы запустите это для гораздо большего набора данных, я думаю, что мой будет более эффективным.

 WITH data AS (
      SELECT "JONES" name, DATE("2019-01-03") date_time, "11" order_id, 10 value       UNION ALL
      SELECT "JONES", DATE("2019-01-05"), "12", 5      UNION ALL
      SELECT "JONES", DATE("2019-06-03"), "13", 3      UNION ALL
      SELECT "JONES", DATE("2019-07-03"), "14", 20     UNION ALL
      SELECT "John", DATE("2019-07-23"), "15", 10    
),
aggs as (
    select name, min(date_time) as first_order_date, min(order_id) as first_order_id, sum(value) as total
    from data
    group by 1
)    
select 
  name,
  first_order_id as f_id,
  first_order_date as f_date, 
  sum(value) as total_value_day3,
  total
from aggs
inner join data using(name)
where date_time < date_add(first_order_date, interval 3 day) -- <= perhaps
group by 1,2,3,5

Обратите внимание, это предполагает, что order_id является последовательным (иначе order_id 11 всегда происходит до order_id 12) в том же самомспособ, которым даты являются последовательными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...