Bigquery возможно ли перебирать список значений и применять функции

#sql #google-cloud-platform #google-bigquery

#sql #google-облачная платформа #google-bigquery

Вопрос:

Можно ли реорганизовать этот SQL?

 SELECT 
  field1,
  field2,
  contact 
FROM 
  `mytable` 
WHERE
  concat = CONCAT(
  (EXTRACT(YEAR FROM DATE_SUB(current_date(), INTERVAL 2 DAY))-1),"/",
  EXTRACT(WEEK(MONDAY) FROM DATE_SUB(current_date(), INTERVAL 2 DAY)),"/",
  EXTRACT(DAYOFWEEK FROM DATE_SUB(current_date(), INTERVAL 2 DAY)))
  OR
  concat = CONCAT(
  (EXTRACT(YEAR FROM DATE_SUB(current_date(), INTERVAL 3 DAY))-1),"/",
  EXTRACT(WEEK(MONDAY) FROM DATE_SUB(current_date(), INTERVAL 3 DAY)),"/",
  EXTRACT(DAYOFWEEK FROM DATE_SUB(current_date(), INTERVAL 3 DAY)))
  OR ...
  OR ...
  OR ... same function, just the INTERVAL value changes

  

Я пытался увидеть ЦИКЛЫ в bigquery, GENERATE_ARRAY и других вещах, но я не могу достичь своей цели: (

Заранее благодарю вас за помощь! 🙂

Ответ №1:

Ниже приведен стандартный SQL для BigQuery

 #standardSQL
create temp function all_conditions(intervals int64) as (
  array(
    select concat(
      (extract(year from date_sub(current_date(), interval value day))-1),"/",
      extract(week(monday) from date_sub(current_date(), interval value day)),"/",
      extract(dayofweek from date_sub(current_date(), interval value day)))
    from unnest(generate_array(1, intervals)) value
  )
);
select 
  field1,
  field2,
  contact 
from `mytable`
where concat in unnest(all_conditions(10))     
  

Ответ №2:

Я не уверен, можете ли вы обернуть OR, который вы используете внутри цикла. Вы также можете попробовать использовать определяемую пользователем функцию (UDF). Использование UDF сделало бы его уже намного более читаемым и компактным. Оберните свой повторяющийся синтаксис SQL в функцию, которая будет выглядеть примерно так:

 CREATE TEMP FUNCTION extractInterval(x INT64) AS (
  CONCAT(
  (EXTRACT(YEAR FROM DATE_SUB(current_date(), INTERVAL x DAY))-1),"/",
  EXTRACT(WEEK(MONDAY) FROM DATE_SUB(current_date(), INTERVAL x DAY)),"/",
  EXTRACT(DAYOFWEEK FROM DATE_SUB(current_date(), INTERVAL x DAY)))
);
  

Затем используйте эту функцию в своем запросе:

 SELECT 
  field1,
  field2,
  contact 
FROM 
  `mytable` 
WHERE
  concat = extractInterval(2)
  OR
  concat = extractInterval(3)
  OR 
  ...
  

Источник

Ответ №3:

Вы можете использовать GENERATE_DATE_ARRAY для построения своего диапазона дат и присоединить его к своему основному запросу или использовать что-то вроде where concat in (select ywd_string from date_range)

 with date_range as (
SELECT day as filler_date
  , CONCAT(
  (EXTRACT(YEAR FROM Day)-1),"/",
  EXTRACT(WEEK(MONDAY) FROM day),"/",
  EXTRACT(DAYOFWEEK FROM day)) as ywd_string
FROM UNNEST(
    GENERATE_DATE_ARRAY(DATE('2020-06-20'), DATE('2020-09-19'), INTERVAL 1 DAY)
) AS day
)