2009-11-24 5 views
2

J'ai deux colonnes:sélectionner top 1 avec un groupe par

namecode name 
050125 chris 
050125 tof 
050125 tof 
050130 chris 
050131 tof 

Je veux regrouper par namecode, et revenir seul le nom avec le plus grand nombre d'occurrences. Dans ce cas, le résultat serait

050125 tof 
050130 chris 
050131 tof 

est avec SQL Server 2000

Répondre

1
SELECT max_table.namecode, count_table2.name 
FROM 
    (SELECT namecode, MAX(count_name) AS max_count 
    FROM 
     (SELECT namecode, name, COUNT(name) AS count_name 
      FROM mytable 
      GROUP BY namecode, name) AS count_table1 
    GROUP BY namecode) AS max_table 
INNER JOIN 
    (SELECT namecode, COUNT(name) AS count_name, name 
    FROM mytable 
    GROUP BY namecode, name) count_table2 
ON max_table.namecode = count_table2.namecode AND 
    count_table2.count_name = max_table.max_count 
0

Je n'ai pas essayé, mais cela devrait fonctionner,

select top 1 t2.* from (
select namecode, count(*) count from temp 
group by namecode) t1 join temp t2 on t1.namecode = t2.namecode 
order by t1.count desc 
1
select distinct namecode 
, (
    select top 1 name from 
      (
      select namecode, name, count(*) 
      from myTable i 
      where i.namecode = o.namecode 
      group by namecode, name 
      order by count(*) desc 
      ) x 
) as name 
from myTable o 
10

J'utilise habituellement ROW_NUMBER() pour y parvenir. Vous ne savez pas comment cela fonctionne avec différents ensembles de données, mais nous n'avons rencontré aucun problème de performance suite à l'utilisation de ROW_NUMBER.

La clause PARTITION BY spécifie la valeur à "grouper" les numéros de lignes, et la clause ORDER BY spécifie comment les enregistrements dans chaque "groupe" doivent être triés. Donc partitionnez l'ensemble de données par NameCode, et obtenez tous les enregistrements avec un numéro de ligne de 1 (c'est-à-dire, le premier enregistrement dans chaque partition, ordonné par la clause ORDER BY).

SELECT 
    i.NameCode, 
    i.Name 
FROM 
(
    SELECT 
     RowNumber = ROW_NUMBER() OVER (PARTITION BY t.NameCode ORDER BY t.Name), 
     t.NameCode, 
     t.Name 
    FROM 
     MyTable t 
) i 
WHERE 
    i.RowNumber = 1; 
0

Voici des exemples que vous pouvez utiliser, mais l'utilisation de la table temporaire est plus efficace que la vue, mais il a été fait sur un petit échantillon de données. Vous voudriez vérifier vos propres statistiques.

--Creating A View 
GO 
CREATE VIEW StateStoreSales AS 
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales' 
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank' 
FROM [dbo].[sales] s 
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id) 
GROUP BY t.state,t.stor_id,t.stor_name 

GO 
SELECT * FROM StateStoreSales 
WHERE Rank <= 1 
ORDER BY TotalSales Desc 

DROP VIEW StateStoreSales 


---Using a Temp Table 
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales' 
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank'  INTO #TEMP 
FROM [dbo].[sales] s 
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id) 
GROUP BY t.state,t.stor_id,t.stor_name 

SELECT * FROM #TEMP 
WHERE Rank <= 1 
ORDER BY TotalSales Desc 

DROP TABLE #TEMP