Problema
Ao trabalhar com dados SCD tipo 2, é fácil ver o estado de uma tabela "a partir de" um determinado momento usando suas colunas de data, por exemplo: valid_from
e valid_to
. Por exemplo:
select * from table
where '2023-11-01' between valid_from and valid_to
Você pode então agrupar ou usar funções de janela para agregar.
Mas e se eu quiser fazer isso repetidamente, para cada data de um intervalo (por exemplo: diariamente)? Não preciso agregar essas datas, apenas dentro de cada uma.
Exemplo
Digamos que eu tenha uma tabela que rastreia o quantity
número de pessoas de cada um reservation_id
. Tanto a quantity
personalidade das pessoas quanto a reservation_status
podem mudar com o tempo, conforme monitorado pela tabela. Cada reserva está anexada a um arquivo event_id
. event_date
está incluído para ajudar a limitar o escopo, se necessário (veja as suposições abaixo).
id_da_reserva | status_reserva | quantidade | ID_do_evento | data do evento | válido de | valido para |
---|---|---|---|---|---|---|
1 | ativo | 4 | 100 | 2023-05-25 | 01/01/2023 | 2023-01-02 |
2 | ativo | 2 | 200 | 07/01/2024 | 01/01/2023 | 03-01-2023 |
3 | ativo | 7 | 100 | 2023-05-25 | 2023-01-02 | 9999-12-31 |
4 | ativo | 1 | 200 | 07/01/2024 | 2023-01-02 | 9999-12-31 |
1 | ativo | 5 | 100 | 2023-05-25 | 03-01-2023 | 9999-12-31 |
5 | ativo | 8 | 100 | 2023-05-25 | 03-01-2023 | 9999-12-31 |
2 | cancelado | 2 | 200 | 07/01/2024 | 04/01/2023 | 9999-12-31 |
6 | ativo | 3 | 100 | 2023-05-25 | 06/01/2023 | 9999-12-31 |
PostgreSQL já que o BigQuery é mais difícil de testar – db-fiddle /SQL:
CREATE TABLE Reservations (
"reservation_id" INTEGER,
"reservation_status" VARCHAR(9),
"quantity" INTEGER,
"event_id" INTEGER,
"event_date" DATE,
"valid_from" DATE,
"valid_to" DATE
);
INSERT INTO Reservations
("reservation_id", "reservation_status", "quantity", "event_id", "event_date", "valid_from", "valid_to")
VALUES
('1', 'active', '4', '100', '2023-05-25', '2023-01-01', '2023-01-02'),
('2', 'active', '2', '200', '2024-01-07', '2023-01-01', '2023-01-03'),
('3', 'active', '7', '100', '2023-05-25', '2023-01-02', '9999-12-31'),
('4', 'active', '1', '200', '2024-01-07', '2023-01-02', '9999-12-31'),
('1', 'active', '5', '100', '2023-05-25', '2023-01-03', '9999-12-31'),
('5', 'active', '8', '100', '2023-05-25', '2023-01-03', '9999-12-31'),
('2', 'cancelled', '2', '200', '2024-01-07', '2023-01-04', '9999-12-31'),
('6', 'active', '3', '100', '2023-05-25', '2023-01-06', '9999-12-31');
Embora isso seja, em última análise, para o BigQuery, a resposta será aceita em qualquer dialeto, desde que seja um tanto genérica.
Premissas
- As datas "a partir de" podem ser uma lista ou intervalo baseado em
valid_from
mínimo/máximo valid_to
de9999-12-31
são os dados mais recentes- Todas as reservas para um determinado evento serão entre
event_date - INTERVAL '2 years'
eevent_date
. Isso não muda nada neste exemplo, mas talvez seja útil para dimensionar (?)
Saída desejada
Gostaria de saber a soma dos quantity
agrupados por event_id
e reservation_status
a partir de cada intervalo (dia).
até a data | ID_do_evento | status_reserva | soma_quantidade |
---|---|---|---|
01/01/2023 | 100 | ativo | 4 |
01/01/2023 | 200 | ativo | 2 |
2023-01-02 | 100 | ativo | 11 |
2023-01-02 | 200 | ativo | 2 |
03-01-2023 | 100 | ativo | 20 |
03-01-2023 | 200 | ativo | 3 |
04/01/2023 | 100 | ativo | 20 |
04/01/2023 | 200 | ativo | 1 |
04/01/2023 | 200 | cancelado | 2 |
06/01/2023 | 100 | ativo | 23 |
Estimativa aproximada dos valores das linhas. Será diferente se usar o intervalo completo de datas.
Eu essencialmente quero fazer o seguinte:
/* Invalid SQL, just for conceptual purposes */
-- Given a list of dates, for each "date":
select
event_id,
reservation_status,
sum(quantity)
from table
where {{date}} between valid_from and valid_to
group by
event_id,
reservation_status
Acredito que isso pode ser feito usando linguagem processual, como um loop for, mas sinto que estou pensando demais nisso e tendo problemas para combinar conceitos mais simples.