【问题标题】:MYSQL: Return results ONLY for the first true encountered SELECT expressionMYSQL:仅返回第一个真正遇到的 SELECT 表达式的结果
【发布时间】:2013-10-02 10:20:53
【问题描述】:

想要的结果:

仅返回遇到的第一个真正的 SELECT 表达式的结果。

解释:

所以,我有三个不同的 SELECT 表达式:

  1. SELECT * FROM table WHERE column1 = 'sometext' AND column2='1'
  2. SELECT * FROM table WHERE column1 = 'someothertext' AND column2='2'
  3. SELECT * FROM table WHERE column1 = 'somethirdtext' AND column2='3'

我想得到 1 的结果。如果 1. 返回 NULL,我想要选择编号 2 的结果。如果选择编号 2. 返回 NULL,我想使用选择编号 3。等等。

请注意,对于每个为真的条件,我预计会返回多行 - 我只想要 SELECT 1) 2) 或 3)(按此顺序)的结果

只返回一个 SELECT 表达式的结果很重要,所以即使 2. 和 3. 会返回一些东西,我也只想要来自 1 的结果。

我现在拥有的代码遵循预期的逻辑,但是当我有多个行被以下某些 SELECTS 返回时,它给了我错误:

1242 - 子查询返回多于 1 行

现在的代码:

SELECT  IFNULL( (SELECT * FROM table WHERE  column = 'sometext'), IFNULL( (SELECT *    FROM table WHERE  column = 'someothertext'), IFNULL( (SELECT * FROM table WHERE  column = 'somethirdtext'), 0 ) ) ) 

【问题讨论】:

  • 你能给我们一个样本数据集吗?

标签: mysql sql control-flow


【解决方案1】:

您正在寻找COALESCE 函数。

SELECT COALESCE(
    (SELECT col FROM t WHERE `column` = 'sometext'),
    (SELECT col FROM t WHERE `column` = 'someothertext'),
    (SELECT col FROM t WHERE `column` = 'somethirdtext')
);

-请注意,子查询不应返回超过 1 行/列。

【讨论】:

  • 在带有子查询的 SQL Server COALESCE 中是一个性能问题 (sillisoft.com/?p=62) 我不知道 MySQL 是否表现出相同的行为,但我认为在替换 ISNULL 之前值得检查一下。跨度>
  • @dazedandconfused 但问题被标记为MySQL,而不是sql-server。在 MySQL 中可以正常工作(即,如果未找到 rown,子查询的结果将被视为NULL
  • 除了问题标签之外,ISNULL在MySQL中不一样,ISNULL在MySQL中接受一个参数,并根据参数是否为NULL返回一个布尔值。此外,即使在 SQL-Server 中,您也不能将 ISNULL 与 3 个条件一起使用,and 在 SQl-Server COALESCE 中与子查询表现出转义行为,即如果第一个条件不为空,则后两个子查询没有被评估(我不能保证总是,但在我所做的所有测试中都是如此)。
  • @alma,它被标记为 mysql 并且反对票不是来自我。我知道这会很好,我只是指出一些 DBS 像 SQL Server 将评估这些子查询 6 次,而不是您可能期望的 3 次。只是指出这一点,以便 OP 进行尽职调查。
  • 我不明白为什么每个人都一直指出这是一个 MYSql 问题。我在最初的评论中承认了这一点。我只是说,当使用 COALESCE 和子查询时,MySQL 可能表现出与 SQL Server 相同的行为。如果是这样,基于 COALESCE 的解决方案可能不会像他希望的那样执行。
【解决方案2】:

我会稍微不同地处理这个问题,因为无论如何每个条件只能返回一行,我会使用以下方法来限制完成的选择次数:

SELECT  *
FROM    table 
WHERE   column IN ('sometext', 'someothertext', 'somethirdtext')
ORDER BY CASE column 
            WHEN 'sometext' THEN 1
            WHEN 'someothertext' THEN 2
            WHEN 'somethirdtext' THEN 3
        END
LIMIT 1;

正如 cmets 中指出的,您也可以使用 FIELD 进行排序:

SELECT  *
FROM    table 
WHERE   column IN ('sometext', 'someothertext', 'somethirdtext')
ORDER BY FIELD(column, 'sometext', 'someothertext', 'somethirdtext')
LIMIT 1;

我认为您可以使用以下方法在每个条件下获得多行:

SELECT  T.*
FROM    Table T
        INNER JOIN
        (   SELECT  Column
            FROM    Table
            WHERE   column IN ('sometext', 'someothertext', 'somethirdtext')
            ORDER BY FIELD(column, 'sometext', 'someothertext', 'somethirdtext')
            LIMIT 1
        ) MinT
            ON MinT.Column = T.Column;

基本上,子查询MinT 的作用与之前相同,按照匹配的条件进行排序。然后获取第一个匹配列的值,并将整个表限制为该值。

Example on SQL Fiddle

【讨论】:

  • +1 嘿,gareth,你也可以使用CASE,而不是FIELD(),例如。 ORDER BY FIELD(column, 'sometext', 'someothertext', 'somethirdtext')
  • @491243 谢谢,我已经编辑了答案。我在 SQL-Server 中完成了 98% 的工作,所以忘记了其他 DBMS 中的一些功能,得到提醒总是很高兴。
  • 只需添加两者,使用CASE 对RDBMS 更友好:)
  • 实际上,在某些情况下,一个条件可能会返回超过 1 行。此外,是否可以引入另一列作为 AND 条件 -> 1) SELECT * FROM table WHERE column = 'sometext' AND column2=1 2) SELECT * FROM table WHERE column = 'someothertext' AND column2=2 3 ) SELECT * FROM table WHERE column = 'somethirdtext' AND column2=3
【解决方案3】:
SELECT t.*
FROM 
      ( SELECT o.column1, o.column2
        FROM 
            ( SELECT 1 AS ord, 'sometext' AS column1, '1' AS column2 UNION ALL
              SELECT 2,        'someothertext',       '2' UNION ALL
              SELECT 3,        'somethirdtext',       '3'
            ) AS o
        WHERE EXISTS
              ( SELECT 1
                FROM table AS td 
                WHERE td.column1 = o.column1
                  AND td.column2 = o.column2
              )
        ORDER BY o.ord 
            LIMIT 1
      ) AS d
    JOIN
      table AS t
        ON  t.column1 = d.column1
        AND t.column2 = d.column2 ;

【讨论】:

  • 导致第 6 行出错(在 '2、'someothertext'、'2' UNION ALL 附近)- 有什么想法缺少吗?似乎是一个很棒的功能,但我不确定我是否理解它。
  • 我的错误,错过了两个选择。
【解决方案4】:

MySQL 不是我的日常数据库,所以我可能对此不屑一顾,但你不能只在子查询上使用 LIMIT 1 吗?

【讨论】:

  • 如果你要否决它,至少解释一下原因。我前面说过 MYSQL 不是我的包,所以我完全愿意从错误中吸取教训。
  • 我没有投反对票,但我怀疑这是因为这是一个相当低质量的答案,没有完全解释 limit 1 会做什么或向 OP 展示如何使用它。它本来更适合作为对该问题的评论。
猜你喜欢
  • 2012-10-15
  • 1970-01-01
  • 2015-10-27
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多