2010-05-31 6 views
3

J'ai une vue simple dans ma base de données MSSQL. Il se compose des domaines suivants:Obtenir les meilleurs enregistrements 'n' par report_id

report_id INT 
ym VARCHAR -- YYYY-MM 
keyword VARCHAR(MAX) 
visits INT 

Je peux facilement obtenir le 10 mot-clé hits avec la requête suivante:

SELECT TOP 10 * 
FROM top_keywords 
WHERE ym BETWEEN '2010-05' AND '2010-05' 
ORDER BY visits DESC 

Maintenant où il devient délicat est là que je dois obtenir les 10 premiers dossiers pour chaque report_id dans la plage de dates indiquée (ym BETWEEN @start_date AND @end_date).

Comment pourrais-je obtenir le top 10 pour chaque report_id? J'ai trébuché sur des suggestions impliquant l'utilisation de ROW_NUMBER() et RANK(), mais ont été largement échoué dans leur mise en œuvre.

Répondre

3

Que diriez-vous

SELECT * 
FROM (SELECT *, 
     ROW_NUMBER() OVER(PARTITION BY report_id ORDER BY (SELECT 0)) AS RN 
     FROM top_keywords 
     WHERE ym BETWEEN '2010-05' AND '2010-05') TK 
WHERE RN <= 10 
+0

+1 Beaucoup plus simple que le mien. Je ne sais pas pourquoi j'ai raccroché en faisant un JOIN complètement inutile! Vous avez laissé un 'SELECT 0' plutôt que des' desc descends '. –

+0

Alors que les autres étaient un peu serviables, c'était presque parfait pour ce dont j'avais besoin. J'ai changé le 'ORDER BY' pour utiliser le champ' visits', et tout va bien. Merci! – Skudd

+0

Cela m'a aidé, merci. –

0

Voulez-vous faire une seule requête ou une série de requêtes? Pour une série de requêtes, vous pouvez

  • Étape 1) Trouver tous les ID de rapport unique
  • Étape 2) Utiliser requête ci-dessus pour la partie supérieure 10 pour ce rapport

Ou voulez-vous vraiment une requête géante qui vous donnera tous les résultats? Combien de résultats voulez-vous, 10 par identifiant de rapport?

+0

Une requête géante est pas nécessairement une mauvaise chose, mais c'est ce que je veux: le top 10 par rapport à l'identifiant. – Skudd

1

Non testé (puisque je n'ai pas MSSQL installer à la maison), mais cela ne devrait être proche ...

with IDs (ID) as (
    select 
    report_id 
    from 
    top_keywords tk 
    where 
    tk.ym between @start_date and @end_date 
    and row_number() over(partition by report_id order by visits desc) <= 10 
) 
    select 
    top.* 
    from 
    top_keywords top 
    join IDs on IDs.ID = top.report_id 
Questions connexes