【问题标题】:How to only run subquery if query has rows?如果查询有行,如何只运行子查询?
【发布时间】:2015-01-08 06:25:53
【问题描述】:

我正在像这样的 mysql 中运行更新查询。它旨在更新 mytable 中记录 5 的 mycount 和 mysum 列当且仅当 mycount 为空。

如果它不为空,则没有要更新的行,但子查询仍会运行,这很昂贵。有什么方法可以创建一个查询,如果有什么要更新的,只会运行子查询?

UPDATE mytable
CROSS JOIN (
  SELECT COUNT(*) thiscount, SUM(mycolumn) thissum
  FROM(
    SELECT mycount, mysum
    FROM <some complicated query>
  )t
)t2
SET mycount=thiscount,
    mysum=thissum
WHERE id=5;
  AND mycount IS NULL;

【问题讨论】:

  • 有什么原因你不能在更新之前做一个SELECT COUNT(*) FROM mytable WHERE id=5 and mycount IS NULL,从而验证该行应该被更新吗?

标签: mysql sql optimization subquery


【解决方案1】:

这个版本应该只在有行的情况下运行子查询。但是,它的缺点是每更新一行都要运行两次:

UPDATE mytable
    SET mycount = (SELECT COUNT(*) as thiscount
                   FROM (SELECT mycount, mysum
                         FROM <some complicated query>
                        ) t
                  ),
        mysum = (SELECT SUM(mycolumn) as thissum
                 FROM (SELECT mycount, mysum
                       FROM <some complicated query>
                      ) t
                 )
    WHERE id = 5 AND mycount IS NULL;

只要子查询不包含mytable,您就可以这样做。

编辑:

我不确定以下是否可以保证有效,但它可能在实践中有效:

UPDATE mytable
    SET mycount = (SELECT (CASE WHEN @x := SUM(mycolumn) THEN COUNT(*)
                                ELSE COUNT(*)
                           END) as thiscount
                   FROM (SELECT mycount, mysum
                         FROM <some complicated query>
                        ) t
                  ),
        mysum = @x
    WHERE id = 5 AND mycount IS NULL;

我只是不认为 MySQL 保证 set 子句的评估顺序。但它通常会按照书面规定进行。

【讨论】:

  • 此解决方案确实有效,但正如您所说,需要两次运行相同的昂贵子查询。没有办法解决吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多