我有两张桌子。 offers
和offer_status
。我想返回offers
中缺少offer_status
行或该表中disabled
列为0的行。
以下是我尝试的方法:
SELECT offers.id,network,campid,name,url FROM offers
LEFT JOIN offer_status ON offers.id = offer_status.sql_id
AND offer_status.user_id='3'
WHERE country='US'
AND offer_status.disabled != '1'
ORDER BY epc DESC LIMIT 7
但是,如果offer_status
中的行不存在(并且JOIN失败),则不起作用。对我来说,似乎它应该仍然有效,因为offer_status.disabled为null。
这项工作:
SELECT offers.id,network,campid,name,url FROM offers
LEFT JOIN offer_status ON offers.id = offer_status.sql_id
AND offer_status.user_id='3'
WHERE country='US'
AND (offer_status.disabled IS NULL OR offer_status.disabled=0)
ORDER BY epc DESC LIMIT 7
但对我来说,这似乎表现得更糟糕,而且我仍然感到很失望,我原来的想法并没有起作用。
上面的OR语句是唯一的方法吗?有更好的方法吗?
答案 0 :(得分:2)
SQL逻辑是一种三态逻辑,状态为TRUE,FALSE和UNKNOWN。 WHERE子句选择条件求值为TRUE的行。
如果将NULL值与任何非空值进行比较,则会得到第三个逻辑状态UNKNOWN(不是标题中声明的FALSE)。这与TRUE不同,因此未选择条件评估为UNKNOWN的行。
您可以使用显式IS NULL测试来检查空值。
AND (offer_status.disabled != '1' OR offer_status.disabled IS NULL)
请注意额外的括号,以确保安全,清晰和准确。
如果性能损失太大,请在offer_status.disabled
列上强制执行NOT NULL约束,然后您不必使用IS NULL测试或OR条件。通常,每个可能都是NOT NULL的列应该是NOT NULL;它使您的数据库更容易使用。
请注意,如果offer_status.disabled
为NULL,则为:
WHERE offer_status.disabled = '1' -- evaluates to UNKNOWN and the row is not selected
WHERE offer_status.disabled != '1' -- evaluates to UNKNOWN and the row is not selected
这是标题中声明的错误'与NULL的比较返回FALSE'之间的差异,以及'与NULL的比较返回UNKNOWN'的实际行为。
答案 1 :(得分:1)
将NULL
(使用=
,<>
,<
,>
等)与其他值进行比较,得出NULL
。而NULL
既不是真的,也不是假的。其次,为了满足WHERE
子句,条件必须评估为真。
所以,你的第二个查询实际上是正确的方法。
为了完整起见,可以(但不建议)使用IF
和IFNULL
等功能重写查询,例如:
WHERE IFNULL(offer_status.disabled, 0) = 0
答案 2 :(得分:0)
如果一个或两个参数为NULL,则比较结果为 NULL,除了NULL-safe&lt; =&gt;平等比较运算符。对于 NULL&lt; =&gt; NULL,结果为true。
所以我认为是的,(disabled IS NULL OR disabled=0)
是必要的。