Eu tenho uma tabela de pedidos
Column | Type | Modifiers
------------+-----------------------------+-----------------------------------------------------
id | integer | not null default nextval('orders_id_seq'::regclass)
client_id | integer | not null
start_date | date | not null
end_date | date |
order_type | character varying | not null
Os dados têm pedidos permanentes não sobrepostos para um client_id e, ocasionalmente, um pedido temporário que substitui o pedido permanente em sua data de início, quando eles têm um client_id correspondente. Existem restrições no nível do aplicativo que impedem a sobreposição de pedidos do mesmo tipo.
id | client_id | start_date | end_date | order_type
----+-----------+------------+------------+------------
17 | 11 | 2014-02-05 | | standing
18 | 15 | 2014-07-16 | 2015-07-19 | standing
19 | 16 | 2015-04-01 | | standing
20 | 16 | 2015-07-18 | 2015-07-18 | temporary
Por exemplo, no 2015-07-18
cliente 16 tem o pedido nº 20, pois é um pedido ativo porque substitui o pedido permanente nº 19. Com alguma confusão, encontrei uma maneira eficiente de consultar IDs de pedidos ativos em uma data.
SELECT id from (
SELECT
id,
first_value(id) OVER (PARTITION BY client_id ORDER BY order_type DESC) active_order_id
FROM orders
WHERE start_date <= ? and (end_date is null OR end_date >= ?)
) active_orders
WHERE id = active_order_id
Se você consultar isso 2015-07-18
como espaços reservados, você obterá
id
----
17
18
20
O plano de consulta dessa consulta em comparação com algumas das minhas outras idéias (como subconsultas que contam o número de pedidos temporários para um cliente em uma data) é muito pequeno e estou muito feliz com isso. (o design da mesa, não estou emocionado)
Agora, preciso encontrar todos os pedidos ativos para um período associado às datas em que eles estão ativos. Por exemplo, com o período de 2015-07-18
até 2015-07-19
eu gostaria do seguinte resultado.
active_date | id
------------+----
2015-07-18 | 17
2015-07-18 | 18
2015-07-18 | 20
2015-07-19 | 17
2015-07-19 | 18
2015-07-19 | 19
A ordem 20 substitui a ordem 19 ativada, 2015-07-18
mas não ativada 2015-07-19
.
Descobri generate_series()
que posso gerar um intervalo de datas, mas não faço ideia de como associá-lo a isso para obter uma tabela de datas e IDs de pedidos. Meu palpite é uma junção cruzada, mas não consigo descobrir como fazer isso funcionar nessa circunstância.
obrigado
ATUALIZAÇÃO Adicionado um violino sql .
fonte
Respostas:
Eu usaria em
select distinct on
vez da função de janela, depois juntei os dias.http://sqlfiddle.com/#!15/5a420/16/0
Eu posso elaborar mais se algo não estiver claro.
fonte
distinct on
é ainda mais otimizado do que a consulta da janela. A propósito, devo mencionar que este é um problema comum "top de grupo" no SQL: stackoverflow.com/questions/3800551/…Escreva uma função que utilize uma única data como parâmetro e retorne uma lista de data + IDs que têm um pedido.
Em seguida, use o generate_series conforme sugerido e chame a função no período.
Essa é uma estratégia comum ao lidar com condições complexas no SQL.
Incluímos algum código abaixo, mas a resposta SQL acima é muito mais simples.
Aqui está a função:
E como chamá-lo:
SQLFiddle
fonte