2012-03-27 82 views
4

如何筛选仅符合某些标准的组与其他组相比较的组的结果集?例如,只有那些组织记录数量最多的组织?比较SQL组和海誓山盟

我原本以为子查询如下应该做的伎俩:

SELECT * FROM (
    SELECT *, COUNT(*) AS Records 
    FROM  T 
    GROUP BY X 
) t HAVING Records = MAX(Records); 

然而,除了在一个空的记录最终HAVING条款的结果......这是怎么回事?

+1

如果的Juho的回答不会给你你需要什么,请输入您的数据库类型使用(oracle,mysql,sql server等)(通过使用标签,你把sql放在哪里。如果你只需要通用的SQL解决方案,请在消息正文中提及)。如果您已花时间在您的文章和sqlfiddle.com中添加一些示例数据和表格结构,您可以更轻松地让人们更深入地查看您的问题。 – 2012-03-27 13:41:20

+1

@LevinMagruder:MySQL 5.1;示例数据http://sqlfiddle.com/#!3/b4306/4 – eggyal 2012-03-27 13:49:08

+0

好吧,我不使用mysql,但有人会告诉你一个比我在下面显示的更简单的查询,将他们的答案标记为答案,但是如果我的回答很有帮助,而且你想向我发射upvote,谢谢。如果你有很多像这样的问题,也许还会阅读标签为“每个组最多的问题”的问题,那么有很多有趣的方法。 – 2012-03-27 14:00:00

回答

1

对于你给出的确切问题,一种看待它的方法是你想要一组记录,其中没有其他组具有更多记录。所以,如果你说

SELECT taxid, COUNT(*) as howMany 
GROUP by taxid 

你得到所有县及其计数

然后你就可以把这个表达式,通过使其子查询表,并给它一个别名。在下面,我将查询的两个“副本”分配给名称X和Y,并要求在一张表中没有更多的taxids。如果有两个相同的号码,我会得到两个或更多。不同的数据库具有专有语法,特别是TOP和LIMIT,这使得这种查询变得更简单,更易于理解。

SELECT taxid FROM 
(select taxid, count(*) as HowMany from flats 
GROUP by taxid) as X 

WHERE NOT EXISTS 
(
SELECT * from 
(
    SELECT taxid, count(*) as HowMany FROM 
    flats 
    GROUP by taxid 
    ) AS Y 
    WHERE Y.howmany > X.howmany 
) 
+0

我知道,通过在'WHERE'子句中重复子查询,我可以提取最大行数(只需使用'max()'就可以正常工作),但是调用相同子查询倍;有没有什么办法可以引用WHERE子句中'FROM'子句中子查询产生的临时表? – eggyal 2012-03-27 14:00:57

0

试试这个:

SELECT * FROM (
    SELECT *, MAX(Records) as max_records FROM (
    SELECT *, COUNT(*) AS Records 
    FROM T 
    GROUP BY X 
) t 
) WHERE Records = max_records 

我很抱歉,我现在不能测试此查询的有效性。

+0

第二级查询中的“SELECT MAX(记录)”会将记录集截断为只有一个记录,其中“记录”和“max_records”字段不一定相同(因此总体结果将只包含零或一个记录);也许这是我的原始查询所暗示的,因此没有结果? – eggyal 2012-03-27 13:43:21

4

在MySQL(我假设你正在使用,因为你已经张贴SELECT *, COUNT(*) FROM T GROUP BY X这将在我所知道的所有RDBMS失败)。您可以使用:

SELECT T.* 
FROM T 
     INNER JOIN 
     ( SELECT X, COUNT(*) AS Records 
      FROM T 
      GROUP BY X 
      ORDER BY Records DESC 
      LIMIT 1 
     ) T2 
      ON T2.X = T.X 

这在MySQL进行了测试,并删除隐式分组/聚集。

如果你可以使用窗口功能,并与领带或公用表表达式TOP/LIMIT的一个变得更短:

窗口函数+ CTE:(MS SQL-服务器& PostgreSQL的测试)

WITH CTE AS 
( SELECT *, COUNT(*) OVER(PARTITION BY X) AS Records 
    FROM T 
) 
SELECT * 
FROM CTE 
WHERE Records = (SELECT MAX(Records) FROM CTE) 

窗口函数与TOP(测试MS SQL服务器)

SELECT TOP 1 WITH TIES * 
FROM ( SELECT *, COUNT(*) OVER(PARTITION BY X) [Records] 
      FROM T 
     ) 
ORDER BY Records DESC 

最后,我从来没有使用甲骨文所以apolgies没有添加一个解决方案,在oracle上工作...


编辑

我的解决方案对于MySQL并没有考虑到的关系,和我的一个解决这种对脚趾的步骤建议你所说的你想避免(副本子查询),所以我不知道我能帮助毕竟,但是只是在情况下,优选这里是你的提琴要求,将工作的一个版本:

SELECT T.* 
FROM T 
     INNER JOIN 
     ( SELECT X 
      FROM T 
      GROUP BY X 
      HAVING COUNT(*) = 
        ( SELECT COUNT(*) AS Records 
         FROM T 
         GROUP BY X 
         ORDER BY Records DESC 
         LIMIT 1 
        ) 
     ) T2 
      ON T2.X = T.X 
+0

第一个(mysql)的确会失去联系;这可能是eggyal想要的,如果不是的话,我认为你必须将它改写成与count相匹配。后两者不会失去联系。 – 2012-03-27 14:27:09

+0

@LevinMagruder是的,几分钟前注意到了这一点,添加了一个编辑,但现在我也不认为这是OP所要的,因为它重复了子查询,但据我所知,这是不可避免的。 – GarethD 2012-03-27 14:30:29

+0

+1比我的“不存在”逻辑更直接。 – 2012-03-27 14:31:36