【问题标题】:Return NULL for missing values in an IN list为 IN 列表中的缺失值返回 NULL
【发布时间】:2014-06-13 15:59:12
【问题描述】:

我有一张这样的桌子:

 id | val
 ---------
  1 | abc
  2 | def
  5 | xyz
  6 | foo
  8 | bar

和类似的查询

 SELECT id, val FROM tab WHERE id IN (1,2,3,4,5)

返回

 id | val
 ---------
  1 | abc
  2 | def
  5 | xyz

有没有办法让它在缺少 id 时返回 NULLs,即

 id | val
 ---------
  1 | abc
  2 | def
  3 | NULL
  4 | NULL
  5 | xyz

我想应该有一个棘手的 LEFT JOIN 本身,但我无法理解它。

编辑:我看到人们认为我想按顺序“填补空白”,但实际上我想要的是用 NULL 替换 IN 列表中的缺失值。比如这个

 SELECT id, val FROM tab WHERE id IN (1,100,8,200)

应该返回

 id | val
 ---------
  1 | abc
100 | NULL
  8 | bar
200 | NULL

此外,顺序并不重要。

EDIT2:只需添加几个相关链接:

【问题讨论】:

  • 你可以用数字表左连接。
  • @hovanessyan 它不是重复的(嗯,至少不是那个问题)——因为这个问题是关于存在序列的 sql server 的——这与 mysql 在这个问题上有很大的不同跨度>

标签: mysql sql


【解决方案1】:

是的,你可以。但这会很棘手,因为 MySQL 中没有序列

我假设你想要任何选择,所以它是:

SELECT
  *
FROM
  (SELECT
   (two_1.id + two_2.id + two_4.id + 
   two_8.id + two_16.id) AS id
   FROM
   (SELECT 0 AS id UNION ALL SELECT 1 AS id) AS two_1
   CROSS JOIN (SELECT 0 id UNION ALL SELECT 2 id) AS two_2
   CROSS JOIN (SELECT 0 id UNION ALL SELECT 4 id) AS two_4
   CROSS JOIN (SELECT 0 id UNION ALL SELECT 8 id) AS two_8
   CROSS JOIN (SELECT 0 id UNION ALL SELECT 16 id) AS two_16
   ) AS sequence
  LEFT JOIN
    t
    ON sequence.id=t.id
WHERE
  sequence.id IN (1,2,3,4,5);

(check the fiddle)

它将作为 2 的幂的组合来生成连续的数字表。您的值被传递给WHERE 子句,因此您可以在那里替换任何一组值。

我建议您在这种情况下使用应用程序 - 因为它会更快。如果您想在其他地方(即在其他一些查询中)使用此行集,这可能有一定的意义 - 但如果不是,这对您的应用程序来说是一项工作。

如果您需要更高的值,请向序列生成器添加更多行,例如 fiddle

【讨论】:

  • 您能否提供一个适用于我更新示例的版本:id IN (1,100,8,200)?谢谢。
  • 您需要为此添加更多行来序列化(在我的示例中,最大值为 32。但您需要添加更多 2 的幂才能获得更高的值)。我已经更新了案例 200(即 255 和 two_128
  • 知道了,有趣的想法。不过,fthiella 的回答对我来说看起来更直接。
  • 是的,但是..换个方式想一想:使用上面的查询(即 2 的幂和),您只需要 log2(N) 即可生成 N 行序列,而在 "普通”案例是.. N
【解决方案2】:

你可以使用这个技巧:

SELECT v.id, t.val
FROM
  (SELECT 1 AS id
   UNION ALL SELECT 2
   UNION ALL SELECT 3
   UNION ALL SELECT 4
   UNION ALL SELECT 5) v
  LEFT JOIN tab t
  ON v.id = t.id

请看小提琴here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-13
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    • 2015-08-20
    相关资源
    最近更新 更多