J'ai un tableau des commandes
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
Les données ont des ordres permanents qui ne se chevauchent pas pour un client_id et parfois une commande temporaire qui remplace l'ordre permanent à sa date_début lorsqu'ils ont un client_id correspondant. Des contraintes au niveau de l'application empêchent le chevauchement des commandes du même type.
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
Par exemple, sur le 2015-07-18
client 16, l'ordre n ° 20 est actif car il remplace l'ordre permanent n ° 19. Avec un peu d'histoires, j'ai trouvé un moyen efficace de rechercher des identifiants de commande actifs à une date.
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
Si vous interrogez ceci avec 2015-07-18
comme espaces réservés, vous obtiendrez
id
----
17
18
20
Le plan de requête sur cette requête par rapport à certaines de mes autres idées (comme les sous-requêtes comptant le nombre de commandes temporaires pour un client à une date) est assez petit et j'en suis assez satisfait. (la conception de la table, je ne suis pas ravi)
Maintenant, j'ai besoin d'un pour trouver toutes les commandes actives pour une plage de dates jointes aux dates auxquelles elles sont actives. Par exemple, avec la plage de dates de 2015-07-18
à 2015-07-19
j'aimerais le résultat suivant.
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
L'ordre 20 remplace l'ordre 19 activé 2015-07-18
mais pas activé 2015-07-19
.
J'ai trouvé que generate_series()
je peux générer une plage de dates, mais je n'ai pas la moindre idée de la façon de joindre cela à ceci pour obtenir un tableau des dates et des identifiants de commande. Mon intuition est une jointure croisée, mais je ne peux pas comprendre comment faire fonctionner cela dans cette circonstance.
Merci
MISE À JOUR Ajout d'un violon sql .
la source
Réponses:
J'utiliserais
select distinct on
au lieu de la fonction de fenêtre, puis joignais simplement les jours.http://sqlfiddle.com/#!15/5a420/16/0
Je peux en dire plus si quelque chose n'est pas clair.
la source
distinct on
c'est encore plus optimisé que la requête de fenêtre. Soit dit en passant, je dois mentionner qu'il s'agit d'un problème courant de "top-in-group" dans SQL: stackoverflow.com/questions/3800551/…Écrivez une fonction qui prend une seule date comme paramètre et renvoie une liste de date + id qui ont une commande.
Ensuite, utilisez le generate_series comme vous l'avez suggéré et appelez la fonction sur la plage de dates.
Il s'agit d'une stratégie courante pour traiter des conditions complexes en SQL.
J'ai inclus du code ci-dessous, mais la réponse SQL ci-dessus est beaucoup plus simple.
Voici la fonction:
Et comment l'appeler:
SQLFiddle
la source