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.