Выберите строки с максимальным значением столбца по другому столбцу - PullRequest
9 голосов
/ 15 сентября 2009

Это должен быть простой вопрос, но я не могу заставить его работать: (

Как выбрать строки с максимальным значением столбца в качестве группы по другому столбцу?

Например,

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

ID
Del_Index
docgroupviewid

Теперь проблема в том, что я хочу сначала сгруппировать результаты по docgroupviewid, а затем выбрать одну строку из каждой группы docgroupviewid, в зависимости от того, какая из них имеет самый высокий del_index.

Я пытался

SELECT docgroupviewid, max(del_index),id FROM table
group by docgroupviewid

Но вместо того, чтобы вернуть мне правильный id, он возвращает мне самый ранний id из группы с таким же docgroupviewid.

Есть идеи?

Ответы [ 2 ]

11 голосов
/ 15 сентября 2009

Я много раз боролся с этим, и решение состоит в том, чтобы думать о вашем запросе по-другому.

Мне нужна каждая строка DocGroupViewID, где Del_Index является максимальным (максимальным) для всех строк с этим DocGroupViewID:

SELECT
    T.DocGroupViewID,
    T.Del_Index,
    T.ID
FROM MyTable T
WHERE T.Del_Index = (
    SELECT MAX( T1.Del_Index ) FROM MyTable T1
    WHERE T1.DocGroupViewID = T.DocGroupViewID 
)

Это становится более сложным, когда более чем одна строка может иметь одинаковые Del_Index, так как тогда вам нужно каким-то образом выбрать, какую из них показывать.


РЕДАКТИРОВАТЬ: хотел использовать другой вариант

Вы можете использовать функции RANK() или ROW_NUMBER() с CTE, чтобы получить больший контроль над результатами, как показано ниже:

-- fake a source table
DECLARE @t TABLE (
    ID int IDENTITY(1,1) PRIMARY KEY,
    Del_Index int,
    DocGroupViewID int
)

INSERT INTO @t
SELECT 1, 1 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 3, 1 UNION ALL
SELECT 1, 2 UNION ALL
SELECT 2, 2 UNION ALL
SELECT 2, 2 UNION ALL
SELECT 1, 3 UNION ALL
SELECT 2, 3 UNION ALL
SELECT 3, 3 UNION ALL
SELECT 4, 3

-- show our source
SELECT * FROM @t

-- select using RANK (can have duplicates)
;WITH cteRank AS
(
    SELECT
        DocGroupViewID,
        Del_Index,
        ID,
        RANK() OVER
            (PARTITION BY DocGroupViewID ORDER BY Del_Index DESC)
        AS RowRank,
        ROW_NUMBER() OVER
            (PARTITION BY DocGroupViewID ORDER BY Del_Index DESC)
        AS RowNumber
    FROM @t
)
SELECT *
FROM cteRank
WHERE RowRank = 1

-- select using ROW_NUMBER
;WITH cteRowNumber AS
(
    SELECT
        DocGroupViewID,
        Del_Index,
        ID,
        RANK() OVER
            (PARTITION BY DocGroupViewID ORDER BY Del_Index DESC)
        AS RowRank,
        ROW_NUMBER() OVER
            (PARTITION BY DocGroupViewID ORDER BY Del_Index DESC)
        AS RowNumber
    FROM @t
)
SELECT *
FROM cteRowNumber
WHERE RowNumber = 1

Если у вас есть способы сортировки связей, просто добавьте его в ORDER BY.

3 голосов
/ 15 сентября 2009

Вам придется немного усложнить ваш запрос:

select a.docgroupviewid, a.del_index, a.id from table a
    where a.del_index = (select max(b.del_index) from table
        where b.docgroupviewid = a.docgroupviewid)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...