Сравните массив объектов datetime и выберите все строки, где разница между каждым и следующим меньше 7 дней - PullRequest
0 голосов
/ 08 октября 2018

Моя таблица выглядит следующим образом:

Link to screenshot of my table (пока не могу опубликовать изображения)

Я хочу выбрать все имена из моей таблицы, где разница во времени между каждым из даты-времениОбъекты и следующие всегда более 7 дней.Таким образом, из всего вышесказанного я получу только Пола, поскольку первые два раза Адама уже разнесены только на один день.

Лучшее, что я могу придумать, - это получить разницу во времени между наименьшим и наибольшим временем даты в массиве.а затем разделить на array_length (datetime).Так что в основном среднее время всех объектов datetime, но это мне не помогает.

Я использую стандартный SQL на BigQuery

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

Вы можете использовать unnest():

select t.*
from t
where not exists (select 1
                  from (select dt, lag(dt) over (order by dt) as prev_dt
                        from unnest(datetime) dt
                       ) x
                  where dt < datetime_add(prev_dt, interval 7 day
                 );
0 голосов
/ 08 октября 2018

До сих пор неясно, что именно представляет из себя схема ваших данных: на основе макета - похоже, дата и время - это массив, но на основе типа данных, который вы показываете на изображении - это может быть просто обычное поле, поэтому ниже охватывают обакейсы (для BigQuery Standard SQL)

Кейс 1 - повторяющееся поле

#standardSQL
SELECT name
FROM `project.dataset.table`
WHERE 7 < (
    SELECT DATETIME_DIFF(
      datetime, 
      LAG(datetime) OVER(PARTITION BY name ORDER BY datetime), 
      DAY) distance
    FROM UNNEST(datetime) datetime 
    ORDER BY IFNULL(distance, 777)
    LIMIT 1
  ) 

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

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'Adam' name, 
    [DATETIME '2018-07-26T17:55:03', 
      '2018-07-27T17:55:03',
      '2018-06-29T17:55:03',
      '2018-07-16T17:55:03',
      '2018-08-19T17:55:03',
      '2018-07-14T17:55:03'] datetime UNION ALL
  SELECT 'Paul', [DATETIME '2018-08-26T17:55:03',
      '2018-08-18T17:55:03',
      '2018-06-20T17:55:03',
      '2018-08-09T17:55:03',
      '2018-07-16T17:55:03']
)
SELECT name
FROM `project.dataset.table`
WHERE 7 < (
    SELECT DATETIME_DIFF(
      datetime, 
      LAG(datetime) OVER(PARTITION BY name ORDER BY datetime), 
      DAY) distance
    FROM UNNEST(datetime) datetime 
    ORDER BY IFNULL(distance, 777)
    LIMIT 1
  ) 

Случай 2 - обычное (не повторяющееся поле)

#standardSQL
SELECT name FROM (
  SELECT name, 
    DATETIME_DIFF(
      datetime, 
      LAG(datetime) OVER(PARTITION BY name ORDER BY datetime), 
      DAY
    ) distance
  FROM `project.dataset.table`
)
GROUP BY name 
HAVING MIN(distance) > 7

Пример фиктивных данных ниже:

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'Adam' name, DATETIME '2018-07-26T17:55:03' datetime UNION ALL
  SELECT 'Adam', '2018-07-27T17:55:03' UNION ALL
  SELECT 'Adam', '2018-06-29T17:55:03' UNION ALL
  SELECT 'Adam', '2018-07-16T17:55:03' UNION ALL
  SELECT 'Adam', '2018-08-19T17:55:03' UNION ALL
  SELECT 'Adam', '2018-07-14T17:55:03' UNION ALL
  SELECT 'Paul', '2018-08-26T17:55:03' UNION ALL
  SELECT 'Paul', '2018-08-18T17:55:03' UNION ALL
  SELECT 'Paul', '2018-06-20T17:55:03' UNION ALL
  SELECT 'Paul', '2018-08-09T17:55:03' UNION ALL
  SELECT 'Paul', '2018-07-16T17:55:03' 
)
SELECT name FROM (
  SELECT name, 
    DATETIME_DIFF(
      datetime, 
      LAG(datetime) OVER(PARTITION BY name ORDER BY datetime), 
      DAY
    ) distance
  FROM `project.dataset.table`
)
GROUP BY name 
HAVING MIN(distance) > 7   

оба возвращают один и тот же результат

Row name     
1   Paul     
0 голосов
/ 08 октября 2018
SELECT name
FROM dataset.table
WHERE NOT EXISTS(
  SELECT 1 FROM UNNEST(datetime) AS dt WITH OFFSET off
  WHERE DATETIME_DIFF(
    datetime[SAFE_OFFSET(off - 1)], dt, DAY
  ) <= 7
)

Сравнивает каждую запись в массиве с той, которая находится после нее, и ищет любую, где число дней равно 7 или меньше.

...