【问题标题】:IF Condition Perform Query, Else Perform Other QueryIF 条件执行查询,否则执行其他查询
【发布时间】:2013-06-16 11:33:08
【问题描述】:

在 MySQL 之外的任何地方都感觉非常简单。

基本上,我需要根据特定术语返回的结果数量来切换我使用的索引类型以及其他一些条件。

大意是:

IF (SELECT COUNT(*) FROM table WHERE term LIKE "term") > 4000
   EXECUTE QUERY A
ELSE
   EXECUTE QUERY B

这可能在 MySQL 语句中吗?

编辑:

查询 A:

SELECT id 
FROM table_a
FORCE INDEX(id)
JOIN table_b ON table_a.id = table_b.id
WHERE term LIKE "term"
ORDER BY date
LIMIT 100;

查询 B:

SELECT id 
FROM table_a
FORCE INDEX(term)
JOIN table_b ON table_a.id = table_b.id
WHERE term LIKE "term"
GROUP BY term    # These lines would be included for a few conditions not mentioned above.. but are necessary
HAVING COUNT = 1 # same...  
ORDER BY date
LIMIT 100;

查询切换的原因是,根据“术语”的受欢迎程度,我得到的结果时间截然不同。

【问题讨论】:

  • QUERY AQUERY B 具体是什么? SQL 通常允许使用创造性的WHERE 子句来处理这种情况,但我们不能说除非我们知道 A 和 B 是否足够相关。
  • ...否则,MySQL 只允许在函数、触发器和存储过程中使用流控制逻辑——而不是在常规查询中。
  • 理论上 - 是的(借助 CASE 语句和连接),但这取决于两个查询中的字段数和记录数是否匹配。您应该将这两个与测试数据一起发布,以便我们回答。
  • @MichaelBerkowski 我将查询添加到问题中。
  • 您可以同时执行查询 A 和 B,然后使用 CASE 进行计数。如果这不起作用,请查找存储过程

标签: mysql


【解决方案1】:

编辑: 我在下面所说的关于需要存储过程的内容是不正确的。试试这个:

SELECT CASE WHEN ( (SELECT COUNT(*) FROM table WHERE term LIKE "term") > 4000 )
    THEN <QUERY A>
    ELSE <QUERY B>
END

这确实是一个 case 表达式,它在存储过程之外也能正常工作 :-)

例如:

mysql> SELECT CASE WHEN ( 5 > 4 ) THEN ( SELECT 'foo' ) ELSE ( SELECT 'bar' ) END;
+---------------------------------------------------------------------+
| CASE WHEN ( 5 > 4 ) THEN ( SELECT 'foo' ) ELSE ( SELECT 'bar' ) END |
+---------------------------------------------------------------------+
| foo                                                                 |
+---------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql> SELECT CASE WHEN ( 3 > 4 ) THEN ( SELECT 'foo' ) ELSE ( SELECT 'bar' ) END;
+---------------------------------------------------------------------+
| CASE WHEN ( 3 > 4 ) THEN ( SELECT 'foo' ) ELSE ( SELECT 'bar' ) END |
+---------------------------------------------------------------------+
| bar                                                                 |
+---------------------------------------------------------------------+
1 row in set (0.00 sec)

下面是历史兴趣的旧答案,因为它已经收集了赞成票:

我认为您可以使用以下内容,但只能在存储过程中使用:

CASE (SELECT COUNT(*) FROM table WHERE term LIKE "term") > 4000
    WHEN 1 THEN <QUERY A>
    ELSE <QUERY B>
END CASE

这是一个CASE 语句,与CASE 表达式不同...https://dev.mysql.com/doc/refman/5.0/en/case.html 有更多血淋淋的细节。

实际上,我怀疑一般来说,如果您想有条件地执行不同的查询,您将需要查看存储过程——我可能错了,但这是我的直觉。如果你能做到,它可能会使用 CASE 表达式!

最后一个编辑:在任何现实世界的示例中,我可能会在我的应用程序中执行条件位,一旦我决定搜索什么,就将其交给 SQL(或生成我的 SQL 的 ORM)为。

【讨论】:

  • 您可能还应该提到,这仅在查询仅返回 1 行时才有效。否则,您将收到一条错误消息,指出子查询返回多于 1 行。
【解决方案2】:

试试:

select coalesce(i.id, t.id) id
from (SELECT COUNT(*) countterm FROM table WHERE term LIKE "term") c
left join
     (SELECT id, date
      FROM table_a
      FORCE INDEX(id)
      JOIN table_b ON table_a.id = table_b.id
      WHERE term LIKE "term") i on countterm > 4000
left join
     (SELECT id, date
      FROM table_a
      FORCE INDEX(term)
      JOIN table_b ON table_a.id = table_b.id
      WHERE term LIKE "term"
      GROUP BY term
      HAVING COUNT = 1) t on countterm <= 4000
ORDER BY coalesce(i.date, t.date)
LIMIT 100;

【讨论】:

  • 我喜欢这个,因为它提供了正确的输出,但它同时执行了两个查询,我确信 OP 希望避免这种情况。
  • @Bohemian:如果join ... on(对主查询)条件为假,它会真正执行子查询吗?
  • 我会这么认为,因为 ON 条件是一个 mini where 子句 - 一个过滤器 - 用于连接的行,并且条件的错误性无法优化(无法事先知道这将是错误的)。我可能是错的......
  • @MarkBannister,我在上面的答案中取得了一些成功,但是,非常感谢您花时间提供解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-12
  • 1970-01-01
相关资源
最近更新 更多