1
votes

Requête de commande max dans les 10 ans à compter de la première date de commande enregistrée

Je suis censé récupérer la commande maximale dans les 10 ans suivant la première date de commande enregistrée. J'ai essayé la requête suivante:

SELECT C.NAME, O.PRICE FROM CUSTOMERS C
    LEFT JOIN ORDERS O ON C.ORDER_ID = O.ID
    WHERE O.PRICE = (SELECT MAX(PRICE) FROM (SELECT * FROM ORDERS O2 WHERE O2.ORDER_DATE BETWEEN MIN(O2.ORDER_DATE) AND DATEADD(year, 10, MIN(O2.ORDER_DATE))))

mais cela donne l'erreur de:

non dérivable de la table.

Quelqu'un pourrait-il m'aider à signaler mon erreur?


6 commentaires

Vous pouvez utiliser une clause Have pour spécifier la condition de sélection du prix maximum dans la sous-requête.


Veuillez inclure quelques exemples de données et le résultat souhaité.


@HoneyboyWilson pourriez-vous s'il vous plaît élaborer?


@PM désolé mais ceci est une question de test HackerRank donc je ne suis pas autorisé à divulguer les détails


Puis inventez vos propres exemples de données et fournissez le résultat souhaité en fonction de ceux-ci.


Vos conditions de rejoindre semblent défectueuses. Je n'ai pas vu de table clients avec un identifiant de commande.


3 Réponses :


4
votes

Dans votre code, vous utilisez MIN (O2.ORDER_DATE) sans le dériver d'une requête.
De plus, vous n'avez pas besoin de BETWEEN car tout ce dont vous avez besoin est que la date de commande soit antérieure à la date minimale + 10 ans.
Vous pouvez obtenir le prix maximum en triant le résultat de la requête par ordre décroissant et en ne gardant que la 1ère ligne:

SELECT TOP 1 C.NAME, O.PRICE 
FROM CUSTOMERS C INNER JOIN ORDERS O 
ON C.ORDER_ID = O.ID
WHERE O.ORDER_DATE <= DATEADD(year, 10, (SELECT MIN(ORDER_DATE) FROM ORDERS))
ORDER BY O.PRICE DESC

Je suppose que vous utilisez SQL Server, c'est pourquoi j'utilise TOP 1 .


3 commentaires

Merci beaucoup! pourriez-vous également ajouter la version O.PRICE = MAX (PRICE)? Je souhaite vérifier qu'à part l'erreur MIN (O2.ORDER_DATE), ma solution est correcte


La version MAX (PRICE) est moins efficace et plus compliquée: SELECT C.NAME, O.PRICE FROM CUSTOMERS C INNER JOIN ORDERS O ON C.ORDER_ID = O.ID WHERE O.ORDER_DATE <= DATEADD (year, 10 , (SELECT MIN (ORDER_DATE) FROM ORDERS)) AND O.PRICE = (SELECT MAX (PRICE) FROM ORDERS WHERE ORDER_DATE <= DATEADD (year, 10, (SELECT MIN (ORDER_DATE) FROM ORDERS)))


oui, en fait, je pensais utiliser une sorte de fonction de fenêtre (comme indiqué dans la réponse ci-dessous) pour filtrer les commandes qui sont plus de 10 ans à compter de la date de la première commande



1
votes

Utilisez les fonctions de la fenêtre!

select o.*
from (select o.*,
             max(price) over (partition by customer_id) as max_price
      from (select o.*,
                   min(order_date) over (partition by o.customer_id) as first_order_date
            from orders o
           ) o
      where order_date < dateadd(year, 10, first_order_date)
     ) o
where price = max_price;

Je vous laisserai rejoindre la table client pour obtenir le nom et d'autres informations client que vous pourriez souhaiter.

Cela suppose que orders a une colonne customer_id d'une sorte, ce qui correspond normalement à la configuration de ces tables.


1 commentaires

Merci beaucoup! ma solution originale consiste en quelque sorte à suivre cette direction pour filtrer les commandes qui datent de plus de 10 ans à compter de la date de la première commande mais qui n'ont pas fonctionné



0
votes
    CREATE VIEW temp_order AS
    (SELECT PRICE, ID FROM ORDERS 
    WHERE ORDER_DATE <= DATE_ADD((SELECT MIN(ORDER_DATE) FROM ORDERS), INTERVAL 10 YEAR));
    SELECT C.NAME, PRICE 
    FROM CUSTOMERS C JOIN 
    temp_order ON C.ORDER_ID = temp_order.ID 
    WHERE PRICE = (SELECT MAX(PRICE) FROM temp_order);

0 commentaires