Не группируемые столбцы в совокупном запросе - PullRequest
0 голосов
/ 11 апреля 2019

Допустим, у меня есть таблица с тремя столбцами: c1, c2 и c3. Я хочу получить в каждом c1 максимальное значение c2 и значение c3 строки, содержащей максимальное значение.

Вот пример. Скажем, MyTable содержит следующие записи:

c1   c2   c3
---  ---  ---
1    32   12
1    27   15
1    12   21
2    23   33
2    36   49
3    48   17
3    21   50
3    7    25

Тогда мой запрос должен вернуть

c1   MAX(c2)  c3
---  -------  ---
1    32       12
2    36       49
3    48       17

Но когда я запрашиваю

SELECT c1, MAX(c2), c3 FROM MyTable GROUP BY c1

Я получаю ошибку:

Column 'MyTable.c3' is invalid in the select list because it is not 
contained in either an aggregate function or the GROUP BY clause.

Как я могу исправить этот запрос? Я пробовал подзапросы, объединения и т. Д. Безрезультатно.

Ответы [ 3 ]

2 голосов
/ 11 апреля 2019

Я думаю, что коррелированный подзапрос в where - это простое решение:

select t.*
from t
where t.col2 = (select max(t2.col2) from t t2 where t2.col1 = t.col1);

Это часто имеет очень хорошие характеристики производительности.Более традиционное решение использует row_number(:

select t.*
from (select t.*,
             row_number() over (partition by col1 order by col2 desc) as seqnum
      from t
     ) t
where seqnum = 1;

Если у вас есть отдельная отдельная таблица значений col1, тогда apply также может иметь хорошую производительность:

select t.*
from table_col1 c1 cross apply
     (select top (1) t.*
      from t 
      where t.col1 = c1.col1
      order by t.col2 desc
     ) t;
0 голосов
/ 11 апреля 2019

Вы можете воспользоваться предложениями CASE и OVER().

DECLARE 
    @MyTable TABLE(c1 INT, c2 INT, c3 INT)

INSERT INTO @MyTable 
VALUES
(1,    32 ,  12),
(1,    27 ,  15),
(1,    12 ,  21),
(2,    23 ,  33),
(2,    36 ,  49),
(3,    48 ,  17),
(3,    21 ,  50),
(3,    7  ,  25)


SELECT *
FROM (
    SELECT   
        c1
    ,   MAX(c2) OVER(PARTITION BY c1) c2
    ,   CASE WHEN c2 = MAX(c2) OVER(PARTITION BY c1) THEN c3 ELSE NULL END c3
    FROM @MyTable
) D
WHERE 
    c3 IS NOT NULL 
0 голосов
/ 11 апреля 2019

Вы можете попробовать:

SELECT a.c1, a.c2, a.c3 
FROM
MyTable a
INNER JOIN
(SELECT c1, MAX(c2) as 'max_c2' FROM MyTable GROUP BY c1) b
ON
a.c1 = b.c1
AND
a.c2 = b.max_c2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...