MySQL – 从表的id字段中select一个没有对应项的数字列表
我有一个数字列表,说{2,4,5,6,7}我有一个表,foos,与foos.ID,包括说,{1,2,3,4,8,9}
我喜欢拿我的数字列表,并find没有在我的表的ID字段中的对手。
实现这一点的一种方法是创build一个表格栏,在ID字段中加载{2,4,5,6,7}。 那么,我会做的
SELECT bars。* FROM bars LEFT JOIN foos ON bars.ID = foos.ID WHERE foos.ID IS NULL
不过,我想完成这个无临时表。
任何人有任何关于如何发生的投入?
这是一个很常见的问题:在不创build表的情况下即时生成关系。 这个问题的SQL解决scheme非常尴尬。 使用派生表的一个示例:
SELECT n.id FROM (SELECT 2 AS id UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7) AS n LEFT OUTER JOIN foos USING (id) WHERE foos.id IS NULL;
但是这并不是很好,因为你可能有许多价值,而不是六个。 构build一个每个值需要一个UNION
的长列表会变得很烦人。
另一个解决scheme是保存一个十位数的通用表,并将其重复使用以实现多种目的。
CREATE TABLE num (i int); INSERT INTO num (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9); SELECT n.id FROM (SELECT n1.i + n10.i*10 AS id FROM num AS n1 CROSS JOIN num AS n10 WHERE n1.i + n10.i*10 IN (2, 3, 4, 5, 6, 7)) AS n LEFT OUTER JOIN foos USING (id) WHERE foos.id IS NULL;
我显示内部查询生成值从0..99即使这不是必要的情况下。 但是,您的列表中可能有大于10的值。 关键是,用一个表号,你可以生成大量的数字,而不必诉诸一个UNION
每个值很长的链。 另外,您可以在一个地方指定所需值的列表,这是更方便和可读的。
我找不到一个解决scheme,您的精确问题,不使用临时表,但使用子select而不是联接做替代方法是:
SELECT bars.* FROM bars WHERE bars.ID NOT IN (SELECT ID FROM foos)
像我最初写的其他海报一样:
SELECT * FROM foos WHERE foos.ID NOT IN (2, 4, 5, 6, 7)
但后来我意识到,这是产生相反的,你想要的。
如果您使用PHP,则可以在不创build任何临时表的情况下进行此项工作。
SELECT ID FROM foos WHERE foos.ID IN (2, 4, 5, 6, 7)
您可以使用PHP的array_diff()函数将其转换为所需的结果。 如果你的列表(2,4,5,6,7)在一个名为$ list的数组中,并且上面的查询的结果在一个数组$ result中,那么
$no_counterparts = array_diff($list, $result);
…将返回列表中的所有数字,而数据库表中没有对应的数字。 尽pipe这个解决scheme不能在查询中执行完整的操作,但是您需要在PHP中执行的后处理对于获得您想要的function来说是微不足道的,而且避免创build临时表也许是值得的。
我有一个类似的问题。 我有一个自动递增的主键有一些缺失值的范围,所以首先我发现有多less: select count(*) from node where nid > 1962
。 比较这个数字和最高的价值,我得到了数字的缺失。 然后我跑这个查询: select n2.nid from node n1 right join node n2 on n1.nid = (n2.nid - 1) where n1.nid is null and n2.nid > 1962
这会find非连续数缺lesslogging。 它不会显示连续的,我不完全确定如何做到这一点,除了改变ON子句允许更大的纬度(这将使JOIN表大大增加)。 无论如何,这七名失踪的人中,有五人得到了五个结果,另外两人保证在五人中至less有一人。 如果你有更多的人失踪,你可能需要一些其他方式find剩余的失踪。
Alnitak的(和你的)解决scheme应该可以工作,而且我不能只用SQL语言工作。
但是问题来了 – 你如何通过价值清单? 在调用代码中处理这个问题不是更好 – 即请求这个ID并将它比较为冷却代码,这可能是一种更适合这种操作的语言。