【问题标题】:MySQL WHERE IN subquery with multiple columns具有多列的 MySQL WHERE IN 子查询
【发布时间】:2020-06-20 00:54:02
【问题描述】:

我正在创建一个 SQL 查询/子查询,它将返回“上课日”列表。我正在使用的查询似乎无法识别子查询中的值,我不知道为什么。如果我运行子查询,我会得到正确的值。出于某种原因,当我尝试一起运行整个查询和子查询时,它无法正常工作,并且我只能得到逗号分隔列表中第一个值的结果。如果我运行下面的查询,我只会得到 tblclasses.cla_ID = 1234 的结果:

SELECT 
    *
FROM
    classdays
WHERE
    classdays.classday_classid IN (SELECT 
            CONCAT_WS(', ',
                        tclasses.cla_ID,
                        tclasses.cla_nextclass,
                        tclasses_1.cla_nextclass) AS nextclasses
        FROM
            tclasses
                LEFT JOIN
            tclasses AS tclasses_1 ON tclasses.cla_nextclass = tclasses_1.cla_ID
        WHERE
            tclasses.cla_ID = 1234)

但是,如果我只运行子查询,它可以工作并且我得到值列表:1234、5678、9012

(SELECT CONCAT_WS(', ',tclasses.cla_ID,tclasses.cla_nextclass,tclasses_1.cla_nextclass) AS nextclasses
   FROM
       tclasses
   LEFT JOIN
       tclasses AS tclasses_1 ON tclasses.cla_nextclass = tclasses_1.cla_ID
   WHERE
       tclasses.cla_ID = 1234)

如果我像这样简单地使用 IN 语句中的值运行查询,它也可以工作:

SELECT 
    *
FROM
    classdays
WHERE
    classdays.classday_classid IN (1234, 5678, 9012)

任何帮助将不胜感激,因为由于某种原因,我无法让 IN 语句在这 3 个逗号分隔值上运行

谢谢!

【问题讨论】:

  • IN 不适用于逗号分隔的字符串。当您使用x IN (subquery) 时,它会与子查询结果的每一行进行精确比较。
  • 不要将列与CONCAT_WS 合并,而是使用UNION 将它们放在单独的行中。
  • 3 个逗号分隔的值被视为文字字符串'value1, value2, value3'
  • @Barmar - 我以前从未真正使用过 UNION 查询。我了解它的基础知识,但是由于我本质上是在自身上加入同一个表LEFT JOIN tclasses AS tclasses_1 ON tclasses.cla_nextclass = tclasses_1.cla_ID 该 UNION 查询看起来如何?

标签: mysql subquery


【解决方案1】:

您可以在子查询中加入 classdays 但不使用 CONCAT_WS,并在 ON 子句中使用 IN 条件:

SELECT classdays.*
FROM classdays
JOIN (
  SELECT 
    tclasses.cla_ID,
    tclasses.cla_nextclass as next1,
    tclasses_1.cla_nextclass as next2
  FROM tclasses
  LEFT JOIN tclasses AS tclasses_1
    ON tclasses.cla_nextclass = tclasses_1.cla_ID
  WHERE tclasses.cla_ID = 1234
) c ON classdays.classday_classid IN (c.cla_ID, c.next1, c.next2)

如果子查询可以返回多行,或者列表c.cla_ID, c.next1, c.next2 可以包含重复项,您可能需要SELECT DISTINCT classdays.*

Barmar 在UNION 中提到的是

SELECT classdays.*
FROM classdays
WHERE classdays.classday_classid IN (
  SELECT tclasses.cla_ID
  FROM tclasses 
  WHERE tclasses.cla_ID = 1234

  UNION

  SELECT tclasses.cla_nextclass
  FROM tclasses
  WHERE tclasses.cla_ID = 1234

  UNION 

  SELECT tclasses_1.cla_nextclass
  FROM tclasses
  JOIN tclasses AS tclasses_1 ON tclasses.cla_nextclass = tclasses_1.cla_ID
  WHERE tclasses.cla_ID = 1234
)

请注意,前两个 UNION 部分不需要 JOIN。对于最后一部分,您可以使用 INNER JOIN 而不是 LEFT JOIN。

【讨论】:

    【解决方案2】:

    你不能从一个字符串动态地创建一个 IN 列表。

    但你也不需要,你可以将 classdays.classday_classid 加入到子查询返回的集合中。

    【讨论】:

    • 好吧,不能从字符串动态生成 IN 列表是有道理的。关于将 classdays.classday_classid 加入到子查询返回的集合中,我该怎么做,因为它返回了 3 个单独的列,而不是 3 行?我是 SQL 的初学者,对此感到困惑!非常感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 2018-07-19
    相关资源
    最近更新 更多