0

我有两张桌子。offersoffer_status。我想从offersoffer_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

但是,如果 in 中的行offer_status不存在(并且 JOIN 失败),这将不起作用。对我来说,它似乎仍然可以工作,因为 offer_status.disabled 为空。

这确实有效:

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 语句是唯一的方法吗?有没有更好的方法?

4

3 回答 3

2

SQL 逻辑是具有 TRUE、FALSE 和 UNKNOWN 状态的三态逻辑。WHERE 子句选择条件评估为 TRUE 的行。

如果您将 NULL 值与任何非 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'd 条件。通常,可能为 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”的实际行为之间的区别。

于 2012-12-26T07:21:00.423 回答
1

NULL将(使用=, <>,<>)与另一个值进行比较得出NULL. 而且NULL既不是真的,也不是假的。其次,为了满足WHERE子句,条件必须评估为真。

因此,您的第二个查询实际上是正确的方法。

为了完整起见,可以(但不推荐)使用 和 等函数重写您的查询IFIFNULL例如:

WHERE IFNULL(offer_status.disabled, 0) = 0
于 2012-12-26T07:21:29.103 回答
0

引用MySQL 文档

如果一个或两个参数为 NULL,则比较结果为 NULL,但 NULL 安全 <=> 相等比较运算符除外。对于 NULL <=> NULL,结果为真。

所以我认为是的,(disabled IS NULL OR disabled=0)是必要的。

于 2012-12-26T07:21:36.553 回答