Как ограничить набор результатов SQL не слишком общими элементами - PullRequest
3 голосов
/ 28 января 2010

Проблема: у меня есть список имен и адресов. Некоторые имена (лица) имеют такой же адрес (улица, почтовый индекс, город), как и другие. Я хочу выбрать все эти имена с адресами не более трех вхождений, а из остальных - первые три имени, каждое из которых указывает на один и тот же адрес. Пример:

Albert | Adr1
Berta  | Adr1
Cesar  | Adr1
Donald | Adr1
Eric   | Adr2
Fritz  | Adr2
Gerd   | Adr2
Henry  | Adr3

Результирующий набор должен быть
Albert | Adr1 
Berta  | Adr1
Cesar  | Adr1
Eric   | Adr2
Fritz  | Adr2
Gerd   | Adr2
Henry  | Adr3

Дональд пропал, потому что он четвертый в группе с тем же адресом. Можно ли достичь этого результата с помощью UNION и подзапросов? Что-то вроде

select * from addresses where address in 
(select address from addresses group by address having count(address) <= 3)
UNION
select * from addresses where address in 
(select address from addresses group by address having count(address) > 3 limit 3)

Я знаю, что этот запрос неправильный, потому что он ограничивает полный набор результатов адресами более чем 3 случаями. Интересно, можно ли это сделать одним SELECT с помощью UNION и подзапросов? Я сделаю это сейчас процедурно с PHP / MySQL, но просто для интереса заинтересовался бы решением только для SQL.

Я посмотрел на SQL-запрос с ограничением на строки из одной таблицы, а не с набором результатов , но это не отражает мою ситуацию - или нет?

Ответы [ 2 ]

3 голосов
/ 28 января 2010
select name, address
from
 ( select *, row_number() over (partition by address order by name) as namenum
   from yourTable
 ) t
where namenum <= 3;
1 голос
/ 28 января 2010

Вы можете попробовать что-то вроде

SELECT  PersonName,
        Address
FROM    (
            SELECT  *,
                    (SELECT COUNT(1) FROM addresses WHERE Address = a.Address AND PersonName < a.PersonName) CountLess
            FROM    addresses a
        ) sub
WHERE   sub.CountLess <= 2
...