J'essaie de résoudre un problème intéressant. J'ai une table qui a, entre autres données, ces colonnes (dates de cet échantillon sont présentés au format européen - jj/mm/aaaa):Sélectionner des valeurs uniques triés par date
n_place_id dt_visit_date
(integer) (date)
========== =============
1 10/02/2012
3 11/03/2012
4 11/05/2012
13 14/06/2012
3 04/10/2012
3 03/11/2012
5 05/09/2012
13 18/08/2012
Fondamentalement, chaque lieu peut être visité à plusieurs reprises - et les dates peuvent être dans le passé (visites terminées) ou dans le futur (visites planifiées). Par souci de simplicité, les visites d'aujourd'hui font partie des futures visites planifiées.
Maintenant, je dois exécuter une sélection sur cette table, qui rassemblerait ID unique place de cette table (sans date) trié dans l'ordre suivant:
- visites futures vont avant les visites passées
- visites futures ont la priorité dans le tri sur les visites passées pour la même place
- pour vos prochaines visites, la première date doit avoir la priorité dans le tri pour le même endroit
- pour les visites passées, la dernière date doit tak La préséance dans le tri pour le même endroit.
Par exemple, pour les données d'échantillons présentés ci-dessus, le résultat que je besoin est:
5 (earliest future visit)
3 (next future visit into the future)
13 (latest past visit)
4 (previous past visit)
1 (earlier visit in the past)
Maintenant, je peux obtenir le désiré de tri en utilisant case when
dans la clause order by
comme ceci:
select
n_place_id
from
place_visit
order by
(case when dt_visit_date >= now()::date then 1 else 2 end),
(case when dt_visit_date >= now():: date then 1 else -1 end) * extract(epoch from dt_visit_date)
Ce sorte de fait ce dont j'ai besoin, mais il contient des ID répétés, alors que j'ai besoin d'ID uniques. Si j'essaie d'ajouter distinct
à l'instruction select, postgres se plaint que je dois avoir le order by
dans la clause select - mais alors l'unique ne sera plus raisonnable, car j'ai des dates là-bas. D'une manière ou d'une autre, je pense qu'il devrait y avoir un moyen d'obtenir le résultat dont j'ai besoin dans une instruction select, mais je n'arrive pas à comprendre comment le faire.
Si cela ne peut pas être fait, alors, bien sûr, je vais devoir faire le tout dans le code, mais je préférerais avoir cela dans une déclaration SQL.
P.S. Je ne m'inquiète pas de la performance, car le jeu de données que je vais trier n'est pas important. Après l'application de la clause where
, il contiendra rarement plus d'une dizaine d'enregistrements.
J'obtiens l'erreur 'ne peut pas lancer intervalle integer' en ligne' casting ((dt_visit_date - maintenant()) comme int) comme days' –
Essayez le modifier ci-dessus – podiluska
Eh oui! C'est à peu près tout. Il suffit de changer 'SIGN (...)' '1 - SIGN (...)' - et ça a fait l'affaire. Merci beaucoup! –