2016-05-18 1 views
2

У меня есть таблица tab, которая содержит столбцы a,b,c,d. Но следующий запрос не будет работать, поскольку c не находится в разделе group by или в функции сокращения.Как добавить функцию агрегации в негруппированный столбец, который не находится в списке

SELECT a, b, c FROM tab GROUP BY a, b; 

Но что я хочу, чтобы выбрать c на основе максимального значения d. Как это сделать в PostgreSQL?

| a | b | c | d | 
| 1 | 2 | 3 | 100 | 
| 1 | 2 | 4 | 110 | 
| 1 | 2 | 5 | 90 | 

В качестве результата мне нужен результат в строке 2, потому что значение в d является самым высоким.

+0

Пожалуйста, отредактируйте ваш вопрос, добавьте примерные данные и ожидаемый результат на основе этих данных. _Formatted_ текст, пожалуйста, нет [скриншоты] (http://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images-of-code-on-so-when-asking-a- вопрос/285557 # 285557) –

+0

Что делать, если есть 2 значения с одинаковыми 'd' like' 1,2,3,100' и ​​'1,2,4,100'? Вы хотите оба? – lad2025

+0

@ lad2025, хорошая точка :) .. я думаю, что у меня должен быть только один. Тогда мне нужны еще один критерий, чтобы отфильтровать это. Но опять же его другая проблема. – dinesh707

ответ

3

Classic top-n-per-group. Один из способов сделать это с помощью ROW_NUMBER:

WITH 
CTE 
AS 
(
    SELECT 
     a, b, c 
     ,ROW_NUMBER() OVER(PARTITION BY a, b ORDER by d DESC) AS rn 
    FROM tab 
) 
SELECT 
    a, b, c 
FROM CTE 
WHERE rn = 1; 

Индекс по (a, b, d, c) должно помочь.

Подход с ROW_NUMBER хорошо работает, когда таблица имеет несколько строк на группу, и сервер должен читать большую часть таблицы. Например, таблица имеет 1 миллион строк и 800K отдельных групп (a, b). Вам придется читать большинство строк.

Если таблица имеет 1 миллион строк и только 20 различных групп (a, b), было бы лучше сделать 20 запросов соответствующего индекса вместо чтения всех строк.

+1

Правильное и стандартное соответствие. И вместо этого используйте 'RANK' или' DENSE_RANK', если вы хотите рассмотреть связи. –

3

В Postgres можно использовать distinct on:

SELECT DISTINCT ON (a, b) a, b, c 
FROM tab 
ORDER BY a, b, d DESC; 

Этот синтаксис специфичен для Postgres. Часто это самый эффективный способ выполнения этого типа операции.

0

Если у вас есть первичный ключ, , вы можете выбрать max d в подзапросе и внутреннее соединение этого запроса на первичном.

+0

Правильно, что вы можете выбрать 'max (d)' per 'a, b' и использовать это для доступа к данным, о которых идет речь. Однако это не имеет ничего общего с таблицей, имеющей первичный ключ или нет. –

+0

вам нужно какое-то одинаковое значение для соединения, вот что я имел в виду. – Aurora

+0

Ну, вы получаете 'a, b, max (d)' и присоединяетесь к 'a, b, d', конечно :-) –

 Смежные вопросы

  • Нет связанных вопросов^_^