我有一个 mysql 数据库,其中某些表使用实体属性值反模式。我需要查询该表并提取属性。我希望将它们作为布尔值,即左连接为我提供null
(对于不存在的)我想要获取的属性false
,如果该属性存在,我想要获取true
(或 0 和 1)。
select
-- cap.type as over_21 -- ok: some null, some "over_21"
-- coalesce(cap.type, false) as over_21 -- ok: some 0, some "over_21"
-- (case when type is not null then 1 else 0 end) as over_21 -- ok: some 0, some 1
if (cap.type, true, false) as over_21 -- wrong: all 0
-- if (cap.type is null, false, true) as over_21 -- ok again
from customer c
left join capabilities cap
on c.id = cap.user_id
and cap.type = 'over_21'
第一行注释掉的行到目前为止仍然有效,它给出了null
属性类型,这里是“over_21”。(该表没有我可以使用的值字段;如果记录存在,则意味着属性已设置。)
coalesce
及case
以上工作均按预期进行,但是当我使用时if
,该over_21
列仅显示 0。
IF () 函数文档说明:
如果 expr1 为 TRUE(expr1 <> 0 且 expr1 IS NOT NULL),则 IF() 返回 expr2。否则,它返回 expr3。
考虑到我的expr1
有时是null
,我认为这会很好地将它们变成0,将非null
-变成1(或假和真)。它确实适用于显式is null
检查。
为什么不将if
我的null
值转换为布尔值?
NULL 不是布尔值 false,也不是整数 0。
如果它是假的,那么
NOT (NULL)
就是真的,对吧?但事实并非如此:将 NULL 视为“未知”。
如果我不告诉你我的中间名,有人问你比尔的中间名是戴夫吗?你会说“我不知道。”
如果他们问你 Bill 的中间名是不是Dave?你只能再次回答“我不知道”。
测试您的查询:
结果:
那么为什么 user_id 为 1 的结果却是 0 呢?
因为在布尔上下文中,字符串并不隐含地为真。在 MySQL 中,布尔值和整数是相同的,因此这实际上是一个整数上下文。
在整数上下文中求值的字符串会隐式转换为数字,方法是读取任何初始数字字符并忽略其余字符。如果没有初始数字字符,则字符串的数字值为 0。而 0 对 MySQL 来说是假的。