2016-08-15 64 views
2

我有两个表,servicesextraFees,相关的1xn到services.id = extraFees.serviceId。我的问题是,当我对s.ids.category的不存在的组合执行以下查询时,我仍然得到1 row(s) returned,所有字段均为NULL。MIN()导致MySQL返回所有NULL行而不是0行

SELECT 100 + (s.feeRate * MIN(ef.extra)) AS extraFees FROM services s 
LEFT JOIN extraFees ef ON s.id=ef.serviceId WHERE s.id=12 AND s.category='PRG' 

我知道罪魁祸首是MIN(),因为如果我用一个数字或NULL替换它,我得到0 row(s) returned,这就是我想要的。

SELECT 100 + (s.feeRate * 5) AS extraFees FROM services s 
LEFT JOIN extraFees ef ON s.id=ef.serviceId WHERE s.id=12 AND s.category='PRG' 
SELECT 100 + (s.feeRate * NULL) AS extraFees FROM services s 
LEFT JOIN extraFees ef ON s.id=ef.serviceId WHERE s.id=12 AND s.category='PRG' 

为什么会发生这种情况,我该如何避免它?

回答

4

聚合函数将返回结果。试试这个:

CREATE TABLE x(id int); 
SELECT MIN(id) FROM x 

你会得到1行:NULL。

SELECT y.id 
    FROM (SELECT MIN(id) AS id FROM x) y 
    WHERE y.id IS NOT NULL 

或使用HAVING条款:如果你想 忽略NULL结果,您可以在子查询包裹。

4

发生这种情况是因为MIN() returns NULL if there were no matching rows

我该如何避免它?

尝试将调用包装到子查询中的MIN()以过滤出NULL。

编辑:

我读过的文档,但我没有看到MIN()返回的NULL是如何从 我在最后一个查询手动指定NULL不同。

我怀疑这是因为你的第二组查询不是聚合查询。 聚合查询将返回行上的聚合结果。 如果没有行,则查询返回NULL。

另一方面,第二组查询不是聚合查询,那些查询可以返回一个“空集”作为逻辑结果。

+0

我读过那个文档,但是我看不到MIN()返回的NULL与我在最后一个查询中手动指定的NULL不同。 – user3748908

+0

@ user3748908只需使用NULL,不会触发聚合计算,因此在基表上完成所有过滤之后,不会显示任何行。使用'MIN'强制总是返回一行的聚合操作。过滤完成后(不返回任何行),将对空结果集进行聚合计算,结果为具有“NULL”值的一行。 – Glenn