PostgreSQL: как найти идентификаторы с максимальными деньгами в еженедельной таблице - PullRequest
2 голосов
/ 12 декабря 2010

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

# select * from pref_money limit 5;
       id       | money |   yw
----------------+-------+---------
 OK32378280203  |   -27 | 2010-44
 OK274037315447 |   -56 | 2010-44
 OK19644992852  |     8 | 2010-44
 OK21807961329  |   114 | 2010-44
 FB1845091917   |   774 | 2010-44
(5 rows)

В моем списке пользователей PHP-скриптов мне нужно знать, кто был еженедельным победителем, чтобы я мог показывать медали возле ихимена.Итак, я пытаюсь выполнить это утверждение SQL:

# find the weekly winners
$sth = $db->prepare('select id from pref_money 
    where money in 
    (select max(money) from pref_money group by yw)');

$sth->execute();
while ($row = $sth->fetch(PDO::FETCH_ASSOC))
        @$medals[$row['id']]++;

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

Кто-нибудь знает, как изменить оператор SQL, чтобы действительно выбирались только идентификаторы победителя?

Когда я пробуюследующее, я получаю сообщение об ошибке:

# select id, max(money) from pref_money group by yw;
ERROR:  column "pref_money.id" must appear in the 
  GROUP BY clause or be used in an aggregate function

Спасибо!Alex

ОБНОВЛЕНИЕ: PostgreSQL 8.4.5 / CentOS и могут быть связи: -)

Ответы [ 2 ]

3 голосов
/ 12 декабря 2010

Какая версия PostgreSQL?Это легко сделать с помощью функций управления окнами, представленных в 8.4:

select id, yw from (
    select id,
           yw,
           row_number() over(partition by yw order by money desc) as ranking
    from pref_money
) x
where x.ranking = 1

Это будет примерно так в старых версиях:

select id, yw
from pref_money
     join (select yw, max(money) max_money
           from pref_money
           group by yw) max_money
          on pref_money.yw = max_money.yw and pref_money.money = max_money.max_money

Но обратите внимание, что недели, когда два пользователя связываются за максимальные деньги,будет показан дважды в выводе.Если это действительно то, что вы хотите, вы можете сделать это с помощью функций управления окнами, используя rank() вместо row_number()

2 голосов
/ 12 декабря 2010

Предполагается, что PostgreSQL 8.4+ и никто не связывается с позицией победителя в течение данной недели - в этом списке перечислены еженедельные победители:

WITH sample AS (
  SELECT t.id,
         t.yw,
         ROW_NUMBER() OVER(PARTITION BY t.yw
                               ORDER BY t.money DESC) AS rank
    FROM PREF_MONEY t)
SELECT s.id
  FROM sample s
 WHERE s.rank = 1

Если возможны связи, используйте:

WITH sample AS (
  SELECT t.id,
         t.yw,
         DENSE_RANK() OVER(PARTITION BY t.yw
                               ORDER BY t.money DESC) AS rank
    FROM PREF_MONEY t)
SELECT s.id
  FROM sample s
 WHERE s.rank = 1

Я включил столбец yw, если вы хотите / должны фильтровать по столбцу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...