MySQL:包含COUNT个SELECT查询结果作为列(不分组)

时间:2010-09-29 23:16:08

标签: mysql sql mysql-error-1140

我有一个简单的报告发送框架,基本上做了以下事情: 它执行SELECT查询,它根据结果生成一些文本格式的表,它发送电子邮件,并执行UPDATE查询。

该系统是旧系统的概括,其中所有操作都是硬编码的。但是,在将我想要做的所有逻辑推入SELECT查询中时,我遇到了一个问题。

之前,我可以通过以下方式获取文本表的大部分信息:

SELECT Name, Address FROM Databas.Tabl WHERE Status='URGENT';

然后,当我需要额外的电子邮件号码时,也可以:

SELECT COUNT(*) FROM Databas.Tabl WHERE Status='URGENT' AND TimeLogged='Noon';

现在,我不再拥有多个SELECT查询。我想做的是:

SELECT Tabl.Name, Tabl.Address, COUNT(Results.UID) AS Totals
FROM Databas.Tabl
LEFT JOIN Databas.Tabl Results
    ON Tabl.UID = Results.UID
    AND Results.TimeLogged='Noon'
WHERE Status='URGENT';

至少在我看来,这是为了获得所有被选中的行的总数,并且还有一些条件。

实际上,这给了我“1140 - 混合GROUP列,如果没有GROUP BY”错误,没有GROUP列非法。问题是,我不想GROUP BY。我希望这个COUNT冗余地重复SELECT找到的TimeLogged ='Noon'的结果数。或者我想删除AND子句,并在SELECT语句的结果中包含SELECT语句找到的结果数。

GROUP BY不是答案,因为这会导致它只获取某些列中具有相同值的行的COUNT。而COUNT可能甚至不是解决这个问题的方法,尽管这是我想到的。 FOUND_ROWS()不会这样做,因为它需要是辅助查询的一部分,我只得到一个(加上没有涉及LIMIT),并且ROW_COUNT()似乎不起作用,因为它是一个SELECT语句。

我可能完全从错误的角度接近它。但我想要做的是在一个查询中获取有关SELECT查询结果的COUNT类型信息,以及SELECT查询返回的所有其他信息。

===这是我到目前为止所得到的===

SELECT Tabl.Name, Tabl.Address, Results.Totals
FROM Databas.Tabl
LEFT JOIN (SELECT COUNT(*) AS Totals, 0 AS Bonus
           FROM Databas.Tabl
           WHERE TimeLogged='Noon'
           GROUP BY NULL) Results
     ON 0 = Results.Bonus
WHERE Status='URGENT';

这确实使用了我最初希望避免的子SELECT,但现在意识到希望可能是愚蠢的。此外,COUNTing SELECT子查询似乎比主查询更便宜,因为COUNT条件都在一个表上,但我正在使用的真正的SELECT必须连接多个不同的表以获取派生信息。

关键的实现是我可以GROUP BY NULL,它将返回一个结果,这样COUNT(*)将实际捕获所有内容,并且我可以强制通过伪造一个带有0的Bonus列来关联到该列两张桌子。

看起来这是我将使用的解决方案,但直到明天我才能真正接受它作为答案。感谢您的帮助。

5 个答案:

答案 0 :(得分:11)

SELECT Tabl.Name, Tabl.Address, Results.Totals
FROM Databas.Tabl
LEFT JOIN (SELECT COUNT(*) AS Totals, 0 AS Bonus
           FROM Databas.Tabl
           WHERE TimeLogged='Noon'
           GROUP BY NULL) Results
     ON 0 = Results.Bonus
WHERE Status='URGENT';

我认为这要归功于多个答案产生的想法,尽管它实际上并不是任何答案的直接结果。为什么这样做我所需要的已在原始帖子的编辑中解释,但我希望能够用正确的答案解决问题,以防其他人想要执行这种愚蠢的操作。感谢所有帮助过的人。

答案 1 :(得分:2)

你可能会做一个联盟。您必须在原始查询中添加一个列并在其中选择0,然后在第二个查询中选择UNION,这将返回一个列。为此,第二个查询还必须选择空字段以匹配第一个。

SELECT Cnt = 0, Name, Address FROM Databas.Tabl WHERE Status='URGENT'
UNION ALL
SELECT COUNT(*) as Cnt, Name='', Address='' FROM Databas.Tabl WHERE Status='URGENT' AND TimeLogged='Noon';

这有点像黑客,但你想做的事情并不理想......

答案 2 :(得分:1)

这可以满足您的需求吗?

SELECT   Tabl.Name                   ,
         Tabl.Address                ,
         COUNT(Results.UID) AS GrandTotal,
         COUNT(CASE WHEN Results.TimeLogged='Noon' THEN 1 END) AS NoonTotal
FROM     Databas.Tabl
         LEFT JOIN Databas.Tabl Results
         ON       Tabl.UID = Results.UID
WHERE    Status            ='URGENT'
GROUP BY Tabl.Name,
         Tabl.Address
WITH ROLLUP;

答案 3 :(得分:0)

您用来访问数据库的API应该能够向您报告返回了多少行 - 例如,如果您正在运行perl,您可以执行以下操作:

my $sth  = $dbh->prepare("SELECT Name, Address FROM Databas.Tabl WHERE Status='URGENT'");
my $rv   = $sth->execute();
my $rows = $sth->rows;

答案 4 :(得分:0)

按Tabl.id分组我不相信会搞砸结果。试一试,看看那是不是你想要的。