2015-10-04 3 views
3

Я использую PostgreSQL БД и имеют две таблицы, какSQL получить идентификатор максимального счета за официанта

официантов (идентификатор, имя)

векселями (идентификатор , сумма, id_waiter)

, и я ищу идентификатор счета с максимальной суммой на одного официанта.

я нашел следующее решение

SELECT waiter.id AS waiter, maxamount, bills.id AS bill 
FROM waiter 
JOIN (
    SELECT id_waiter, max(amount) AS maxamount 
    FROM bills 
    GROUP BY id_waiter) AS maxis ON maxis.id_waiter = waiter.id 
JOIN bills ON maxis.maxamount = bills.amount AND waiter.id =  bills.id_kellner 

Это работает, но это кажется немного излишним, и мне интересно, если есть лучший способ сделать это. То, что мне не нравится в этом, состоит в том, что счета соединяются дважды, один раз в подзапросе и один раз в конце.

Вот некоторые выборочные данные

Примеры данных

официантов стол

id | name 
1 | john 
2 | joe 

счета стол

id | amount | id_waiter 
1 | 20 | 1 
2 | 25 | 2 
3 | 50 | 2 
4 | 20 | 1 
5 | 60 | 1 
6 | 10 | 2 

Результат выглядит следующим образом

waiter | maxamount | bill 
1 | 60 | 5 
2 | 50 | 3 
+0

Выборочные данные было бы неплохо. .. –

+0

Пример данных добавлен –

ответ

2

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

select distinct on(id_waiter) id_waiter, amount max_amount, id bill 
from bills 
order by 1, 2 desc; 

id_waiter | max_amount | bill 
-----------+------------+------ 
     1 |   60 | 5 
     2 |   50 | 3 
(2 rows)  

На самом деле join бы необходимо, если вы хотите, чтобы выбрать имена официантов тоже:

select id_waiter, name, max_amount, bill 
from (
    select distinct on(id_waiter) id_waiter, amount max_amount, id bill 
    from bills 
    order by 1, 2 desc 
    ) sub 
join waiters w on w.id = id_waiter; 

id_waiter | name | max_amount | bill 
-----------+------+------------+------ 
     1 | john |   60 | 5 
     2 | joe |   50 | 3 
(2 rows)  

SqlFiddle

+1

Thx @klin, это хорошо работает. Если я получу это правильно, с 'distinct on' вы выбираете первую из каждой из групп, которые упорядочены id_waiter и max_amount. Мне интересно о производительности. Мой пример - это абстракция над более сложным и большим набором данных. Я считаю, сортировка немного дороже, чем найти максимальное значение, не так ли? Если я его правильно напомню, то найти максимальное значение должно быть возможно в O (n), а нижняя граница сортировки - O (n log n). Вероятно, их можно уменьшить, сохранив структуры индексных деревьев в столбце количества. Мой фон базы данных не слишком глубокий, извините. –

+1

Вы правы, на неиндексированном столбце max() немного быстрее. На моем сервере это ~ 500 мс ~ 600 мс в пользу max() для 5 миллионов целых чисел. В индексированном столбце разница должна быть слишком малой, чтобы ее можно было заметить. – klin

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