2010-05-26 2 views
1

Мне нужно иметь возможность выбирать только первую строку для каждого имени с наибольшим значением.SQL Server Distinct Question

У меня есть таблица со следующим:

id name value 

0 JOHN 123 
1 STEVE 125 
2 JOHN 127 
3 JOHN 126 

Так что я ищу, чтобы вернуться:

id name value 

1 STEVE 125 
2 JOHN 127 

Любая идея на MSSQL синтаксис о том, как выполнить эту операцию?

ответ

0

Как насчет:

SELECT a.id, a.name, b.maxvalue 
    FROM mytbl a 
INNER JOIN (SELECT id, max(value) as maxvalue 
       FROM mytbl 
      GROUP BY id) b ON b.id = a.id 
+2

Так как 'id' также находится в' GROUP BY', не будет ли это возвращать все записи? Я думаю, что самосоединение, чтобы получить «id», может быть необходимо, и просто «GROUP BY» на 'name' сначала, а затем' JOIN', чтобы получить 'id' –

2

попробовать:

SELECT 
    MIN(id) as id,dt.name,dt.value 
    FROM (SELECT 
       name,MAX(value) as value 
       FROM YourTable 
       GROUP BY name 
     ) dt 
     INNER JOIN YourTable t ON dt.name=t.name and dt.value=t.value 
    GROUP BY dt.name,dt.value 

попробовать:

DECLARE @YourTable table (id int, name varchar(10), value int) 
INSERT @YourTable VALUES (0, 'JOHN', 123) 
INSERT @YourTable VALUES (1, 'STEVE', 125) 
INSERT @YourTable VALUES (2, 'JOHN', 127) 
INSERT @YourTable VALUES (3, 'JOHN', 126) 

--extra data not in the question, shows why you need the outer group by 
INSERT @YourTable VALUES (4, 'JOHN', 127) 
INSERT @YourTable VALUES (5, 'JOHN', 127) 
INSERT @YourTable VALUES (6, 'JOHN', 127) 
INSERT @YourTable VALUES (7, 'JOHN', 127) 

SELECT 
    MIN(id) as id,dt.name,dt.value 
    FROM (SELECT 
       name,MAX(value) as value 
       FROM @YourTable 
       GROUP BY name 
     ) dt 
     INNER JOIN @YourTable t ON dt.name=t.name and dt.value=t.value 
    GROUP BY dt.name,dt.value 
    ORDER BY id 

выход:

id   name  value 
----------- ---------- ----------- 
1   STEVE  125 
2   JOHN  127 

(2 row(s) affected) 
+0

Не возвращает' id' –

+1

он возвращает id сейчас! –

7

Пока вы указали SQL Server, вы не указали версию. Если вы используете SQL Server 2005 или более поздней версии, вы можете сделать что-то вроде:

With RankedItems As 
    (
     Select id, name, value 
      , Row_Number() Over (Partition By name Order By value Desc, id Asc) As ItemRank 
     From Table 
    ) 
Select id, name, value 
From RankedItems 
Where ItemRank = 1 
+0

Лучший ответ IMO, +1 – ajdams

+0

Функции ранжирования облегчают решение этих проблем. –

+0

Это может быть выполнено без использования CTE. По общему признанию, любое решение приведет к тому же базовому запросу. –

0
SELECT a.id, a.name, a.value 
    FROM mytbl a 
INNER JOIN (SELECT name, max(value) as maxvalue 
       FROM mytbl 
      GROUP BY name) b ON b.name = a.name and b.maxvalue = a.value 
2

Вы могли бы сделать что-то вроде

SELECT id, name, value 
FROM (SELECT id, name, value 
      ROWNUMBER() OVER (PARTITION BY name ORDER BY value DESC) AS r 
     FROM table) AS x 
WHERE x.r = 1 ; 

Это не будет работать в SQL Server 2000 и более ранних версий, но это будет невероятно быстро в SQL Server 2005 и 2008