2014-11-12 4 views
2

За столом похожийСовокупное кол дублей

ID | Value 
------------- 
1  | 2 
2  | 10 
3  | 3 
4  | 2 
5  | 0 
6  | 3 
7  | 3 

Я хотел бы подсчитать количество идентификаторов с более высоким Value, для каждого Value, который появляется в таблице, т.е.

Value | Position 
---------------- 
10 | 0 
3  | 1 
2  | 4 
0  | 6 

Это соответствует смещению Value в заказе ORDER BY Value.

Я рассмотрел делать это путем подсчета количества дублей с чем-то вроде

SELECT Value, count(*) AS ct FROM table GROUP BY Value"; 

А потом сложение результата, но я предполагаю, что это не оптимальный способ сделать это (ни я сумел объединить команды соответственно)

Как можно эффективно вычислить это (для нескольких десятков тысяч строк)?

ответ

3

Это похоже на прекрасную возможность для window function rank() (не связанная с этим dense_rank()):

SELECT DISTINCT ON (value) 
     value, rank() OVER (ORDER BY value DESC) - 1 AS position 
FROM tbl 
ORDER BY value DESC; 

rank() начинается с 1, в то время как ваш отсчет начинается с 0, поэтому вычитаем 1.

Добавление DISTINCT шаг (DISTINCT ON здесь немного дешевле) для удаления повторяющихся строк (после подсчет числа). DISTINCT применяется после оконных функций. Подробности в этом связанном с ответом:

Результат точно так, как требуется.
Индекс на value поможет повысить производительность.

SQL Fiddle.

+1

Невероятный. Я бы не подумал, что команда/функция существует! Большое спасибо. Ранг() еще лучше для того, что я пытаюсь сделать, так что все отлично! – CBenni

1

Вы также можете попробовать это, если вы не знакомы с оконными функциями:

SELECT t1.value, COUNT(DISTINCT t2.id) AS position 
    FROM tbl t1 LEFT OUTER JOIN tbl t2 
    ON t1.value < t2.value 
GROUP BY t1.value 

Обратите внимание на автообъединение.

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