Группировать и агрегировать по дням по датам UTC, скорректированным с учетом указанного смещения часового пояса - PullRequest
0 голосов
/ 13 марта 2019

У меня есть запрос, в котором я определяю общее status для определенного дня на основе агрегирования данных по дате UTC в BigQuery, чтобы полученные данные имели следующую форму:

date            status
----            ------
28-feb-2019     0
01-mar-2019     1

Вот запрос, где sample_date_time - это дата UTC в BigQuery.@startDateTime и @endDateTime в настоящее время передаются как даты UTC, которые всегда представляют дневную границу UTC, например:

@startDateTime = '2019-02-28T00:00:00.000Z'

@endDateTime = '2019-03-01T00:00:00.000Z'

select CAST(sample_date_time AS DATE) as date,
       (case when sum(case when status_code >> 0 = 0 then 1 else 0 end) > 0 
             then 0 
        else 
             case when sum(case when status_code >> 0 = 1 then 1 else 0 end) = 1
             then 1
             end
        end) as status 
from (
  with data as
    (
      select
        sample_date_time,
        status_code
      from `my.table` 
      where sample_date_time between @startDateTime and @endDateTime
      order by sample_date_time
    )

  select sample_date_time, status_code
  from data
)
group by date
order by date

Мне нужнопреобразовать мой запрос, чтобы вместо этого он мог агрегировать данные на основе дневных границ для данного часового пояса .Запрос должен возвращать упорядоченную последовательность со столбцом, который представляет номер дня относительно данного часового пояса и предоставленного диапазона дат.Чтобы уточнить, мне нужны данные в следующей форме:

day            status
----           ------
1              0
2              1

@startDateTime и @endDateTime будут переданы как даты ISO_8601, которые всегда будут представлять дневную границу в данном часовом поясе, и будутв формате, который предоставляет смещение часового пояса относительно UTC, например:

@startDateTime = '2019-02-28T00:00:00+11:00'

@endDateTime = '2019-03-01T00:00:00+11:00'

Таким образом, status для дня 1 будет агрегировано между2019-02-28T00:00:00+11:00 и 2019-03-01T00:00:00+11:00

Предполагая, что я могу передать offset в запрос в качестве параметра, и что эффективность не является существенным фактором (я ищубыстрое решение в автономном запросе), как я могу выполнить группировку и вернуть номер дня?

BigQuery, похоже, не имеет функции convert, поэтому я небыть в состоянии использовать что-то подобное в моем group by:

group by convert(sample_date_time, dateadd(hours, offset, sample_date_time))

Любой совет о том, что я должен смотреть, чтобы достичь этого, приветствуется.

Ответы [ 2 ]

2 голосов
/ 13 марта 2019

Я бы конвертировал дату в базе данных, используя часовой пояс.Лично я много этим занимаюсь:

select date(sample_date_time, 'America/New_York') as dte, count(*)
from t
group by dte;

Это только в качестве примера.Ваш запрос явно более сложный.

1 голос
/ 13 марта 2019

Спасибо @Gordon Linoff за простое и элегантное решение, которое позволяет мне сохранять данные в этой форме, но с датами, преобразованными в соответствии с требуемым часовым поясом, то есть:

date (in specified TZ)    status
----------------------    ------
28-feb-2019               0
01-mar-2019               1

Вот мой последний запрос.Это основано на наличии time_zone в виде столбца в моих данных.Он также зависит от начального и конечного диапазона времени и даты, предоставляемых в локализованном выражении времени с использованием следующего формата ISO8601:

`yyyy-mm-ddThh:mm:ss+hh:mm`

(конечное значение +hh:mm представляет относительное смещение часового пояса, примененное кначальное выражение даты и времени, т.е. yyyy-mm-ddThh:mm)

select date(localised_sample_date_time) as localised_date,
       (case when sum(case when status_code >> 0 = 0 then 1 else 0 end) > 0 
             then 0 
        else 
             case when sum(case when status_code >> 0 = 1 then 1 else 0 end) = 1
             then 1
             end
        end) as status 
from (
  with data as
    (
      select
        DATETIME(sample_date_time,time_zone)as localised_sample_date_time,
        status_code
      from `my.table` 
      where sample_date_time between '2019-03-01T00:00:00.000+1:00' and '2019-03-02T23:59:59.000+1:00' -- get data for the the 1st March (relative to Central European Standard Time i.e. UTC+1)
      order by sample_date_time
    )

  select localised_sample_date_time, status_code
  from data
)
group by localised_date
order by localised_date

time_zone = действительный часовой пояс BigQuery, например, «Австралия / Виктория» - см. https://cloud.google.com/dataprep/docs/html/Supported-Time-Zone-Values_66194188

...