2

Let's say I have something as basic as

SELECT IF( (1 + 2) >=0, (1 + 2), 0)
FROM DUAL

which will obviously return 3.

Is there a way to NOT repeat the query I want to return (here 1 + 2)?

To put in context, I want to return the number of tasks remaining to do for the current month (at least 4 must be done), but if more than 4 are already done, there is no need to do more so I want to return 0.

What I have done is

IF((4 - IFNULL((LONG QUERY RETURNING THE NUMBER OF TASKS DONE THIS MONTH FOR A PARTICULAR USER ),0)) >= 0,
(4 - IFNULL((LONG QUERY RETURNING THE NUMBER OF TASKS DONE THIS MONTH FOR A PARTICULAR USER ), 
0)

But is there a way to not repeat the query since it is long and I don't want the server to execute the same query twice?

4

3 回答 3

4

根据您的要求,您可能希望使用用户定义的变量

SELECT 1+2 INTO @tmp;
SELECT IF( @tmp >=0, @tmp, 0)

或者如果你喜欢一个衬垫

SELECT IF( (@tmp := (1+2)) >=0, @tmp, 0)
--         ^             ^
--        don't forget those parenthesis !

编辑:这也适用于“表选择”语句:

CREATE TABLE tbl AS SELECT 1 as a UNION SELECT 2;
SELECT SUM(a) FROM tbl INTO @tmp;
SELECT IF ( @tmp > 0, @tmp, 0);

如果您查看http://sqlfiddle.com/#!2/37c33/1获取上述查询的执行计划SELECT,您会看到第二个不使用表。


顺便说一句,请注意,在您的实际示例中,这可能是这样写的:

SELECT MAX( (1+2), 0 )
--          ^^^^^ here your expression

...但我认为这不是真正查询的属性?

于 2013-08-08T13:53:01.250 回答
2

你可以这样做:

SELECT IF( (@a:=(1 + 2)) >=0, @a, 0);
于 2013-08-08T13:54:14.533 回答
1

一个语句解决方案

在 MySQL 中解决这个问题的一种方法是保存繁重查询的输出并多次重用。看看这里:

SELECT CASE 
  WHEN @Value - 4 > 0 
  THEN @Value ELSE 0 
  END
FROM (SELECT @Value := (SELECT 1)) Query

其中 «SELECT 1» 应替换为您的查询。

旧约

另一种执行查询的方法需要 CTE(公用表表达式)的支持。

据我所知,MySQL 中缺少此功能(如何将 MSSQL CTE 查询转换为 MySQL?

只是为了让您体验它在 MSSQL 中的表现力,在 CTE 可用的地方,您可以编写如下内容:

with Query (value) 
as
(
    select 1
 )
select 
  case
    when (select value from Query) - 4 > 0
      then (select value from Query)
    else
      0
  end

事实上,CTE 更强大,尤其是在处理递归关系时。

于 2013-08-08T14:11:37.447 回答