我在LEFT JOIN
转换为CHAR
后尝试INT
。像这样:
SELECT o.title, d.title FROM original o
LEFT JOIN directory d ON CONVERT(o.directory_index, UNSIGNED INT) = d.index
如果索引大于零,这会给我正确的响应。但是如果索引为零或空字符串,我会得到每个目录标题的行的重复:
o.title (o.index) d.title (d.index)
"Big Boss" "2" "OUTER HEAVEN" 2
"Snake" "0" "FOX" 0
"Snake" "0" "FOXHOUND" 1
"Snake" "0" "OUTER HEAVEN" 2
"Kerotan" "" "FOX" 0
"Kerotan" "" "FOXHOUND" 1
"Kerotan" "" "OUTER HEAVEN" 2
所以我添加了COALESCE
语句将每个空字符串转换为NULL
值:
SELECT o.title, d.title FROM original o
LEFT JOIN directory d ON CONVERT(
CASE WHEN COALESCE(o.directory_index, '') = '' THEN NULL ELSE o.directory_index END,
UNSIGNED INT
) = d.index
COALESCE
语句确实给了我正确的响应(我单独测试了函数的输出),但现在每个目录标题得到NULL
,除非索引设置为{{1在这种情况下,我得到与以前相同的结果:
0
我做错了什么?
根据建议,我删除了o.title (o.index) d.title (d.index)
"Big Boss" "2" NULL 2
"Snake" "0" "FOX" 0
"Snake" "0" "FOXHOUND" 1
"Snake" "0" "OUTER HEAVEN" 2
"Kerotan" "" NULL 0
"Kerotan" "" NULL 1
"Kerotan" "" NULL 2
语句,并将其换成COALESCE
语句:
NULLIF
但是我遇到了与SELECT o.title, d.title FROM original o
LEFT JOIN directory d ON CONVERT(
NULLIF(o.directory_index, ''),
UNSIGNED INT
) = d.index
语句相同的结果。
我创建了Fiddle我提供的示例,奇怪的是它给了我想要的结果。但这不是我在Workbench中获得的结果。服务器正在运行旧版本的MySQL(我认为5.1?)可能是问题吗?
好的......所以我很尴尬。昨天我整天都在撞墙。然后我今天早上来看看它,结果发现COALESCE
被设置为LEFT JOIN ... ON ... = d.index
。我将在这个帖子上向所有人投票。但我希望你们都投票给我和/或标记要关闭的问题。
答案 0 :(得分:3)
COALESCE
不会用NULL值替换空字符串。相反,它返回列表中的第一个非NULL表达式。
要用NULL替换零长度字符串,可以使用各种表达式...
NULLIF(expr,'')
IF(expr='',NULL,expr)
CASE WHEN expr = '' THEN NULL ELSE expr END
要将字符串(CHAR,VARCHAR)表达式转换为数字值,您可以使用速记:
expr + 0
但是不能保证返回UNSIGNED INT,甚至是整数值。
原始回答
这里缺少的是`directory`表中`directory_index`列的定义和`original`表中的`index`列。
这些列的数据类型是什么?它们中的任何一个都是可空的,还是独一无二的?是否存在外键关系?
无法回答你的问题"我做错了什么"如果我们不知道你想要达到的是什么。
乍一看,连接条件看起来比它需要的复杂得多。
你能解释为什么这个没有(或者不会)工作吗?
SELECT o.title
, d.title
FROM original o
LEFT
JOIN directory d
ON d.directory_index = o.index
ORDER BY ...
您试图通过在连接条件中添加函数来解决问题?
您似乎意识到数据类型转换(从CHAR到INT等)并且您似乎意识到MySQL将隐式地执行大量这些数据类型转换。您可以将这些数据类型转换显式化,并且可以覆盖MySQL默认执行的操作。
在数值上下文中,MySQL会将空字符串计算为0,而不是NULL。作为一个简单的演示,
SELECT '' + 0
但是,再一次,你想要实现的目标是什么?
这是少量样本数据和预期输出将澄清规范的地方。
如何实现该结果实际上取决于表达式中使用的列的实际数据类型以及要返回的内容。
任何"试试这个"我们提出的建议只是猜测,而不是答案。
答案 1 :(得分:1)
这有点令人困惑,因为你的查询看起来像是在查看o.directory_index ...但你的数据显示o.index(这可能是你的错误吗?) 无论如何,试试这个。
SELECT o.title,d.title
FROM original o
LEFT JOIN directory d
ON (CASE WHEN o.directory_index IS NULL OR o.directory_index = '' THEN -1
ELSE CONVERT(o.directory_index,UNSIGNED INT)
END) = d.index;
sqlfiddle 如果CONVERT()是旧MySQL版本中的错误...也许可以尝试CAST()
SELECT o.title,d.title
FROM original o
LEFT JOIN directory d
ON (CASE WHEN o.directory_index IS NULL OR o.directory_index = '' THEN -1
ELSE CAST(o.directory_index as UNSIGNED INT)
END) = d.index;
由于CONVERT()与UNSIGNED INT有一个错误....为什么不尝试CONVERT()到CHAR ......就像这样(可能不行,但值得一试)。
SELECT o.title,d.title
FROM original o
LEFT JOIN directory d
ON o.directory_index = CONVERT(d.index,CHAR);