2010-04-10 5 views
0

Essayez de travailler sur une requête qui retournera les 3 meilleurs produits avec les trois ayant un artiste distinct. Je suis coincé sur l'obtention de l'artiste unique.Distinction avec Count et SQl Server 2005

schéma Tableau simplifié

Product 
    ProductID 
    Product Name 
    Artist Name 

OrderItem 
ProductID 
Qty 


So results would look like this... 

PID artist     qty 
34432, 'Jimi Hendrix',  6543 
54833, 'stevie ray vaughan' 2344 
12344, 'carrie underwood', 1 
+0

Un artiste peut avoir plusieurs produits pour la requête ne doit pas tirer Jimi Hendrix 2x dans les résultats. – Todd

+0

Mais la valeur de la quantité est-elle la valeur unique la plus élevée pour l'artiste, ou la somme de toutes les quantités? –

+0

Il veut que les trois artistes réussissent le mieux à produire des albums individuels. – egrunin

Répondre

2

Utilisez ceci:

with summed_sales_of_each_product as 
(
    select p.artist_name, p.product_id, sum(i.qty) as total 
    from product p join order_item i 
    on i.product_id = p.product_id 
    group by p.artist_name, p.product_id 
), 
each_artist_top_selling_product as 
(
    select x_in.artist_name, x_in.product_id, x_in.total 
    from summed_sales_of_each_product x_in where total = 
     (select max(x_out.total) 
      from summed_sales_of_each_product x_out 
      where x_out.artist_name = x_in.artist_name) 
) 
select top 3 
artist_name, product_id, total 
from each_artist_top_selling_product 
order by total desc 

Mais vous ne pouvez pas arrêter à cette requête, que diriez-vous s'il y a deux produits sur un artiste qui sont cravates sur la vente la plus élevée? Voici comment les données comme celui-ci ...

beatles yesterday  1000 
beatles something  1000 
elvis jailbreak rock 800 
nirvana lithium   600 
tomjones sexbomb   400 

... se traduira par la suite en utilisant la requête ci-dessus:

beatles yesterday  1000 
beatles something  1000 
elvis jailbreak rock 800 

Lequel choisir? hier ou quelque chose? Puisque vous ne pouvez pas arbitrairement choisir l'un sur l'autre, vous devez énumérer les deux. Aussi, que se passe-t-il si le top 10 des ventes les plus importantes appartient aux beatles et sont des cravates, chacune avec une quantité de 1000? Puisque c'est la meilleure chose que vous évitez (la déclaration même artiste sur 3), vous devez modifier la requête afin que le top 3 rapport ressemblera à ceci:

beatles yesterday  1000 
beatles something  1000 
elvis jailbreak rock 800 
nirvana lithium   600 

Modifiant:

with summed_sales_of_each_product as 
(
    select p.artist_name, p.product_id, sum(i.qty) as total 
    from product p join order_item i 
    on i.product_id = p.product_id 
    group by p.artist_name, p.product_id 
), 
each_artist_top_selling_product as 
(
    select x_in.artist_name, x_in.product_id, x_in.total 
    from summed_sales_of_each_product x_in 
    where x_in.total = 
     (select max(x_out.total) 
      from summed_sales_of_each_product x_out 
      where x_out.artist_name = x_in.artist_name) 
), 
top_3_total as 
( 
    select distinct top 3 total 
    from each_artist_top_selling_product 
    order by total desc 
) 
select artist_name, product_id, total 
from each_artist_top_selling_product 
where total in (select total from top_3_total) 
order by total desc 

Que diriez-vous si les beatles ont un autre produit qui a 900 qté? La requête ci-dessus fonctionnera-t-elle toujours? Oui, ça marchera toujours. Puisque le top_3 CTE ne s'occupe que de la quantité supérieure déjà filtrée sur chaque artiste. Donc, cette source de données ...

beatles yesterday  1000 
beatles something  1000 
beatles and i love her 900 
elvis jailbreak rock 800 
nirvana lithium   600 
tomjones sexbomb   400 

...résultera toujours à ce qui suit:

beatles yesterday  1000 
beatles something  1000 
elvis jailbreak rock 800 
nirvana lithium   600 
+0

Très bien Michael! Merci à tous pour votre aide. – Todd

-1

Essayez cette

Select artiste top 3, count (artiste) du groupe tablename par ordre artiste par nombre artiste (artiste) desc

1

Si je comprends votre schéma correctement, vous devriez être capable de le faire comme ceci:

select top 3 * from(
    select p.ProductId, p.ArtistName, sum(o.qty) as qty from Product p, OrderItem o 
    where p.ProductId = o.ProductId 
    group by p.productId, p.ArtistName 
    order by sum(o.qty) 
) 
+0

essayé de l'exécuter mais obtenir cette erreur. Msg 1033, niveau 15, état 1, ligne 7 La clause ORDER BY n'est pas valide dans les vues, les fonctions inline, les tables dérivées, les sous-requêtes et les expressions de table communes, sauf si TOP ou FOR XML est également spécifié. – Todd

0

En analysant votre demande, il semble que les résultats devraient être la plus grande quantité de produits pour les trois meilleurs artistes. Donc, si Jimi Hendrix a les 10 premières quantités de produits et Stevie Ray Vaughan est 11e, vous voulez Jimi avec son produit le plus élevé, puis Stevie avec son produit le plus élevé.

With ProductRanksForArtists As 
    (
    Select P.ProductId, P.ArtistName, Sum(O.Qty) As Total 
     , ROW_NUMBER OVER(PARTITION BY P.ArtistName ORDER BY Sum(O.Qty) DESC) As ProductRank 
    From Product As P 
     Join OrderItem As O 
      On O.ProductId = P.ProductId 
    Group By P.ProductId, P.ArtistName 
    ) 
    , HighestProductForArtists As 
    (
    Select ProductId, ArtistName, Total 
     , ROW_NUMBER OVER(ORDER BY Total DESC) As TotalRank 
    From ProductRanksForArtists 
    Where ProductRank = 1 
    ) 
Select ProductId, ArtistName, Total 
From HighestProductForArtists 
Where TotalRank <= 3 
+0

toujours récupérer deux des mêmes artistes dans les trois enregistrements. – Todd

+0

@chopps - J'ai révisé ma requête. – Thomas

1

Je ne sais pas ce que vous voulez faire si un artiste a deux produits de premier rang avec des ventes identiques - ce sera de retour dans deux cas d'égalité.

Si vous souhaitez ajouter un autre critère, tel que "le plus récent", vous devez l'ajouter aux deux sous-requêtes.

select top 3 sales_by_item.ProductID, 
      sales_by_item.Artist, 
      sales_by_item.Qty 
from 
(
    select * from product x 
    inner join OrderItem y 
    on x.productid = y.productid 
    group by productid, Artist 
) sales_by_item 
inner join 
(
    select artist, max(qty) as maxqty 
    from product x 
    inner join OrderItem y 
    on x.productid = y.productid 
    group by artist 
) max_by_artist 
on sales_by_item.artist = max_by_artist.artist 
    and sales_by_item.qty = max_by_artist.maxqty 
order by sales_by_item.qty 

Edité pour rendre les noms des sous-requêtes plus descriptif

0

Deuxième tentative. Je ne suis pas en mesure de tester ce code, et je ne suis pas sûr si j'ai cette clause "partition par" configuré correctement. L'idée est:

  • La requête interne obtient la somme de tous les produits pour Quantité/artistes, et utilise la fonction row_number() pour les numéro commençant par le plus grand, et remet à zéro la commande pour chaque artiste. (Cela peut être fait, mais ma syntaxe peut être désactivée.)
  • La requête externe sélectionne le premier (le plus grand) élément pour chaque artiste et renvoie uniquement les trois premiers (ordere by Qty)
  • Si un artiste top Deux produits cravates pour un total de Qté, je casse arbitrairement la cravate en faveur de l'album "le plus ancien".

(j'essaie d'éviter d'utiliser « Top n », mais il est tard et je ne veux pas aborder une autre fonction row_number().)

SELECT top 3 
    ProductId 
    ,ArtistName 
    ,Qty 
from (-- Products + Artists by total qty 
     select 
     pr.ProductId 
     ,pr.ArtistName 
     ,sum(oi.Qty) Qty 
     ,row_number() over (partition by pr.ArtistName order by pr.ArtistName, sum(oi.Qty) desc, pr.ProductId) Ranking 
     from Product pr 
     inner join OrderItem oi 
     on oi.ProductID = pr.ProductID 
     group by pr.ProductId, pr.ArtistName) BestSellers 
where Ranking = 1 
group by ProductId, ArtistName) BestArtists 
order by Qty desc 
+0

Non, attendez, ce (v1) ne va pas fonctionner ... –

+0

Ok, v2 semble mieux –