在一个表中使用逗号分隔列表作为另一个表的查询中的子句

时间:2013-10-16 15:14:35

标签: mysql

我有一个events表,其中包含一个名为breaks的字段。这是以逗号分隔格式填充的数据,即1,2,311,4,5 - 与MySQL的IN命令使用的格式相同。

然后,我想在slots表上运行查询,以返回events.breaks中指定的所有行。

理论上,查询应该是这样的:

SELECT
    `slots`.`id` AS id,
    RIGHT(`slots`.`time`, 8) AS `time`
FROM
    `slots`, `event`
WHERE
    `slots`.`id` NOT IN (`event`.`breaks`)

但这似乎不起作用 - 如果event.breaks4,5,7slots表中唯一不返回的行是4

SQLFiddle:http://sqlfiddle.com/#!2/913fe/1/0

3 个答案:

答案 0 :(得分:3)

您将单个字段传递给NOT IN()子句,而不是子表达式。可以这样想想

(1, 2, 3)

大致相同
SELECT 1
UNION
SELECT 2
UNION
SELECT 3;

作为子表达式。你正在做的是

('4,5,7')

大致相当于

SELECT '4,5,7';

反过来,MySQL可能转换为数字进行比较,结果是

NOT IN (4)

你真正想做的事情并不是真的应该这样做。如果你添加了一个AxB关系表,那就更好了,这样就可以用你不想要的ID选择几行。

答案 1 :(得分:2)

尝试一下:

SELECT slots.id AS id, RIGHT(slots.time, 8) time
FROM slots, event
WHERE FIND_IN_SET(slots.id, event.breaks) = 0

这就是FIND_IN_SET(str,strlist)函数的工作原理:

  

如果字符串str位于由N个子字符串组成的字符串列表strlist中,则返回1到N范围内的值。字符串列表是由用“,”字符分隔的子字符串组成的字符串。 [...]如果str不在strlist中,或者strlist是空字符串,则返回0。

另请注意,IN (val1, val2, val3)IN (val4)不同,其中val4是以逗号分隔的字符串。 IN子句将通过相等进行比较。

答案 2 :(得分:0)

您可能需要使用子选择来返回拆分字符串

... NOT IN (SELECT your_split_fnc(`event`.`breaks`) FROM `events`)

请在此处查看答案,了解在MySQL Can Mysql Split a column?

中拆分字符串的方法

instr()MySQL函数也可以提供帮助

... INSTR(event.breaks,id) = 0

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_instr