我有一个简单的报告发送框架,基本上做了以下事情: 它执行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列来关联到该列两张桌子。
看起来这是我将使用的解决方案,但直到明天我才能真正接受它作为答案。感谢您的帮助。
答案 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分组我不相信会搞砸结果。试一试,看看那是不是你想要的。