Mon ensemble de données ressemble à ceci. Pour chaque combinaison d'identifiant client, d'identifiant de commande et de date d'expédition, je souhaite récupérer 1 date de traitement inférieure ou égale à la date d'expédition. Si la date de traitement est supérieure à la date d'expédition et qu'aucune date de traitement inférieure n'existe, utilisez la date d'expédition comme date de traitement.
+-------------+----------+------------+--------------+--+ | Customer ID | Order ID | Ship Date | Process Date | | +-------------+----------+------------+--------------+--+ | 1000 | 100 | 9/17/2020 | 9/17/2020 | | | 2000 | 200 | 8/15/2020 | 8/13/2020 | | | 2000 | 300 | 10/14/2020 | 10/13/2020 | | | 3000 | 400 | 3/4/2020 | 3/3/2020 | | | 4000 | 500 | 5/1/2020 | 5/1/2020 | | | 5000 | 600 | 6/1/2020 | 6/1/2020 | | | 6000 | 700 | 7/14/2020 | 7/13/2020 | | +-------------+----------+------------+--------------+--+
Sortie désirée
+-------------+----------+------------+--------------+--+ | Customer ID | Order ID | Ship Date | Process Date | | +-------------+----------+------------+--------------+--+ | 1000 | 100 | 9/17/2020 | 9/17/2020 | | | 1000 | 100 | 9/17/2020 | 10/16/2020 | | | 1000 | 100 | 9/17/2020 | 9/16/2020 | | | 2000 | 200 | 8/15/2020 | 8/13/2020 | | | 2000 | 300 | 10/14/2020 | 10/13/2020 | | | 3000 | 400 | 3/4/2020 | 4/2/2020 | | | 3000 | 400 | 3/4/2020 | 3/3/2020 | | | 3000 | 400 | 3/4/2020 | 3/5/2020 | | | 4000 | 500 | 5/1/2020 | 5/3/2020 | | | 5000 | 600 | 6/1/2020 | 7/1/2020 | | | 5000 | 600 | 6/1/2020 | 7/2/2020 | 6000 | 700 | 7/14/2020 | 7/13/2020 | | | 6000 | 700 | 7/14/2020 | 6/10/2020 | | +-------------+----------+------------+--------------+--+ | | +-------------+----------+------------+--------------+--+
J'ai essayé d'utiliser ROWNUM
et la différence de date, mais je suis bloqué après avoir obtenu le numéro de ligne dans l'ordre croissant. Je ne sais pas comment procéder.
3 Réponses :
Je pense que vous voulez filtrer et row_number()
:
select t.* from (select t.*, row_number() over (partition by customer_id, order_id, ship_date order by process_date desc) as seqnum from t where process_date <= ship_date ) t where seqnum = 1;
Je ne sais pas si customer_id
et ship_date
sont vraiment nécessaires dans la clause partition by
. order_id
semble suffisant.
Merci Gordon. Je viens de réaliser que j'ai oublié d'ajouter une autre condition. Je viens de modifier la question d'origine pour la refléter. Apprécier ton aide.
" Si la date de traitement est supérieure à la date d'expédition et qu'aucune date de traitement inférieure n'existe, utilisez la date d'expédition comme date de traitement. "
Faites un GROUP BY
. Vous pouvez utiliser MAX()
pour renvoyer le dernier ProcessDate <= ShipDate. Si aucun ProcessDate n'existe, renvoyez ShipDate.
select CustomerID, orderID, ShipDate, coalesce(MAX(case when ProcessDate <= ShipDate then ProcessDate end), ShipDate) from tablename group by CustomerID, orderID, ShipDate
Merci, Jarlh. Cela a été extrêmement utile!
Cela devrait renvoyer le résultat attendu:
select CustomerID, orderID, ShipDate, -- If the process date is greater than the ship date and no lower -- process date exist, then use the ship date as the process date least(ProcessDate, ShipDate) from tablename qualify -- retrieve 1 process date that is less than or equal to the ship date row_number() over (partition by CustomerID, orderI order by case when ProcessDate <= ShipDate then ProcessDate end desc nulls last) = 1
Merci Dnoeth. Cependant, cela récupère 9/16 pour le client 1000 mais j'espérais obtenir 9/17. Et si un client a plusieurs dates d'expédition identiques, et s'il y a des dates de traitement inférieures aux dates d'expédition (aucune date de traitement supérieure ou égale à la date d'expédition, alors celle dont la date d'expédition est la plus proche doit être sélectionnée. Exemple de client 6000 ci-dessus)
Modification de la commande pour qu'elle corresponde à votre nouvelle description.