2008-09-30 6 views
3

Dans MS Transact SQL, disons que j'ai une table (commandes) comme ceci:problème sous-requête SQL avec regroupement, moyenne

Order Date  Order Total  Customer # 
09/30/2008  8.00   1 
09/15/2008  6.00   1 
09/01/2008  9.50   1 
09/01/2008  1.45   2 
09/16/2008  4.50   2 
09/17/2008  8.75   3 
09/18/2008  2.50   3 

Ce que je dois sortir de c'est: pour chaque client la commande moyenne montant pour les deux derniers ordres. Donc, pour le client n ° 1, je devrais obtenir 7,00 (et non 7,83).

J'ai regardé cela pendant une heure maintenant (à l'intérieur d'un plus gros problème, que j'ai résolu) et je pense que mon cerveau a gelé. Aide pour un problème simple?

+0

Quelle version de SQL Server? – Sklivvz

+0

un client peut avoir plusieurs commandes dans une journée? –

Répondre

5

Ceci devrait

select avg(total), customer 
from orders o1 
where orderdate in 
    (select top 2 date 
    from orders o2 
    where o2.customer = o1.customer 
    order by date desc) 
group by customer 
+0

Peut ne pas fonctionner s'il y a plus d'une commande un jour donné, par ex. si pour un client vous avez 3 commandes sur un jour. la sous-requête vous donnera 2 enregistrements de la même date, et la requête supérieure prendra en compte les 3 ordres - mais ce n'est peut-être pas un scénario réel dans le contexte. – kristof

+0

Dans un scénario de la vie réelle, la colonne de date stocke également l'heure, donc ce ne serait pas un problème. – albertein

+0

Vous pouvez également cibler le TOP 2 sur le CreatedDate de l'enregistrement, si votre OrderDate a seulement une "résolution de jour". Si vous avez un CreatedDate, c'est. ;-) – Tomalak

0

Dans SQL Server 2005, vous avez la fonction RANK, utilisée avec la partition:

USE AdventureWorks; 
GO 
SELECT i.ProductID, p.Name, i.LocationID, i.Quantity 
    ,RANK() OVER 
    (PARTITION BY i.LocationID ORDER BY i.Quantity DESC) AS 'RANK' 
FROM Production.ProductInventory i 
    INNER JOIN Production.Product p 
     ON i.ProductID = p.ProductID 
ORDER BY p.Name; 
GO 

Link

+0

Cela a une touche d'overkill. Y a-t-il une bonne raison de le faire comme ça, sur le plan de la performance? – Tomalak

+0

Oui, fonctionne beaucoup mieux qu'une sous-requête. – Sklivvz

+0

En termes de? Il doit y avoir une bonne raison de détourner de ce que quelques lignes de SQL standard peuvent faire avec un résultat égal. – Tomalak

0

Une option serait pour vous d'utiliser un curseur pour parcourir tous les identifiants du client, puis faites les moyennes sous la forme de plusieurs sous-requêtes.

Avertissement correct, cependant, pour les grands ensembles de données, les requêtes ne sont pas très efficaces et peuvent prendre beaucoup de temps à traiter.