2010-01-28 7 views
3

问题:我有一个名称和地址列表。一些姓名(人)与其他人一样具有相同的地址(街道,邮政编码,城镇)。我想选择地址不超过三次的所有这些名称,其余的前三个名称分别指向同一个地址。 例子:如何将SQL结果集限制为不太常见的项目

 
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

唐纳德丢失,因为他是用同一个地址组的第4位。 这个结果可以通过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个出现次数。 我不知道这是否可以用UNION和子查询在单个SELECT中完成。我现在将用PHP/MySQL程序执行它,但只是为了好玩,会对仅限SQL的解决方案感兴趣。

我看了一下SQL query with limit on rows from one table, not the result set,但这并不反映我的情况 - 或者不是吗?

+0

你怎么能认识到,唐纳德是该组的第四成员?这些数据如何分类? – Beatles1692 2010-01-28 09:33:46

+0

这是MySql还是Sql Server? – 2010-01-28 09:53:36

+0

排序顺序无关紧要。它必须是超过3个中的任何3个地址。 服务器是MySQL 5.1 – 2010-01-28 11:45:57

回答

1

你可以尝试像

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 
+0

非常巧妙。非常感谢。 – 2010-01-28 12:07:46

3
select name, address 
from 
(select *, row_number() over (partition by address order by name) as namenum 
    from yourTable 
) t 
where namenum <= 3; 
+1

这是SQL标准吗? – 2010-01-28 09:54:16

+0

这适用于SQL Server,并且Oracle和DB2也都支持OVER子句。我不认为mysql已经赶上了这部分标准,就像SQL Server不需要分号一样。 – 2010-01-28 10:47:11

+0

这不被MySQL支持。该解决方案将我指向http://explainextended.com/2009/09/14/mysql-emulating-row_number-with-multiple-order-by-conditions/,但是,在解决类似问题的同时,Robs解决方案的功能被仿效。 – 2010-01-28 11:55:21