JOIN 转换为整数后的字符串
JOIN on a String After Converted to Integer
我正在尝试 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
,除非索引设置为 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
但我得到的结果与 COALESCE
语句相同。
我创建了一个 Fiddle 我提供的例子,奇怪的是它给了我我想要的结果。但这不是我在 Workbench 中得到的结果。服务器 运行 是 MySQL 的旧版本(我认为是 5.1?)这可能是问题所在吗?
好吧...所以我很尴尬。我昨天一整天都在用头撞墙。然后我今天早上过来一看,原来应该是LEFT JOIN ... ON ... = d.index
的被设置成了LEFT JOIN ... ON ... = d.title
。我将 up-vote 这个话题上的每个人。但我希望你们都给我投反对票 and/or 将问题标记为关闭。
COALESCE
不会用 NULL 值替换空字符串。相反,它 return 是列表中的第一个非 NULL 表达式。
要用 NULL 替换零长度字符串,您可以使用多种表达式...
NULLIF(expr,'')
IF(expr='',NULL,expr)
CASE WHEN expr = '' THEN NULL ELSE expr END
而要将字符串 (CHAR, VARCHAR) 表达式转换为数值,您可以使用 as shorthand:
expr + 0
但这不能保证 return 一个 UNSIGNED INT,甚至是一个整数值。
下面的原始答案
这里缺少的是“目录”table 中的“directory_index”列和“原始”table 中的“索引”列的定义。
这些列的数据类型是什么?它们中的任何一个都可以为空,还是唯一的?是否存在外键关系?
如果我们不知道您要实现的目标,则无法回答您的问题 "What am I doing wrong"。
乍一看,连接条件看起来比需要的复杂得多。
你能解释一下为什么 这个 不起作用(或不会)吗?
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
但是,再次强调一下,您要实现的目标是什么?
这里有少量示例数据,预期输出会阐明规范。
如何实现该结果实际上取决于表达式中使用的列的实际数据类型,以及您想要什么 returned。
我们提出的任何 "try this" 建议都只是猜测,而不是答案。
这有点令人困惑,因为您的查询看起来像 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);
我正在尝试 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
,除非索引设置为 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
但我得到的结果与 COALESCE
语句相同。
我创建了一个 Fiddle 我提供的例子,奇怪的是它给了我我想要的结果。但这不是我在 Workbench 中得到的结果。服务器 运行 是 MySQL 的旧版本(我认为是 5.1?)这可能是问题所在吗?
好吧...所以我很尴尬。我昨天一整天都在用头撞墙。然后我今天早上过来一看,原来应该是LEFT JOIN ... ON ... = d.index
的被设置成了LEFT JOIN ... ON ... = d.title
。我将 up-vote 这个话题上的每个人。但我希望你们都给我投反对票 and/or 将问题标记为关闭。
COALESCE
不会用 NULL 值替换空字符串。相反,它 return 是列表中的第一个非 NULL 表达式。
要用 NULL 替换零长度字符串,您可以使用多种表达式...
NULLIF(expr,'')
IF(expr='',NULL,expr)
CASE WHEN expr = '' THEN NULL ELSE expr END
而要将字符串 (CHAR, VARCHAR) 表达式转换为数值,您可以使用 as shorthand:
expr + 0
但这不能保证 return 一个 UNSIGNED INT,甚至是一个整数值。
下面的原始答案
这里缺少的是“目录”table 中的“directory_index”列和“原始”table 中的“索引”列的定义。
这些列的数据类型是什么?它们中的任何一个都可以为空,还是唯一的?是否存在外键关系?
如果我们不知道您要实现的目标,则无法回答您的问题 "What am I doing wrong"。
乍一看,连接条件看起来比需要的复杂得多。
你能解释一下为什么 这个 不起作用(或不会)吗?
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
但是,再次强调一下,您要实现的目标是什么?
这里有少量示例数据,预期输出会阐明规范。
如何实现该结果实际上取决于表达式中使用的列的实际数据类型,以及您想要什么 returned。
我们提出的任何 "try this" 建议都只是猜测,而不是答案。
这有点令人困惑,因为您的查询看起来像 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);