1

我正在尝试将LEFT JOINaCHAR转换为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声明一样。

我创建了我提供的示例的小提琴,奇怪的是它给了我想要的结果。但这不是我在 Workbench 中得到的结果。服务器正在运行旧版本的 MySQL(我认为是 5.1?)这可能是问题吗?


好吧……所以我很尴尬。我昨天一整天都在用头撞墙。然后我今天早上进来看看它,原来应该LEFT JOIN ... ON ... = d.index设置为LEFT JOIN ... ON ... = d.title。我将在这个线程上投票给每个人。但我希望你们都对我投反对票和/或将问题标记为关闭。

4

2 回答 2

4

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 

但是,再一次,你想要达到什么目的?

这是少量样本数据和预期输出将阐明规范的地方。

如何实现该结果实际上取决于表达式中使用的列的实际数据类型以及您想要返回的内容。

我们提出的任何“试试这个”建议都只是猜测,而不是答案。

于 2016-04-14T19:29:45.993 回答
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);

sqlfiddle

于 2016-04-14T19:52:45.267 回答