【问题标题】:MySQL SubQueries for multiple SUMs多个 SUM 的 MySQL 子查询
【发布时间】:2011-02-12 20:25:11
【问题描述】:

如果我需要在 WHERE 条件相似的情况下获得五个以上不同的 SUM 值,最好(也许是唯一的)方法是通过一个包含五个子查询的查询来做到这一点?例如,我的查询是:

SELECT user, 
(SELECT SUM(amount) FROM table t, table2 t2 WHERE t.table2_id = t2.id AND table2.type = 1 AND user = 1 AND date = x) AS one,
(SELECT SUM(amount) FROM table t, table2 t2 WHERE t.table2_id = t2.id AND table2.type = 2 AND user = 1 AND date = x) AS two, 
(SELECT SUM(amount) FROM table t, table2 t2 WHERE t.table2_id = t2.id AND table2.type = 3 AND user = 1 AND date = x) AS three, 
(SELECT SUM(amount) FROM table t, table2 t2 WHERE t.table2_id = t2.id AND table2.type = 4 AND user = 1 AND date = x) AS four, 
(SELECT SUM(amount) FROM table t, table2 t2 WHERE t.table2_id = t2.id AND table2.type = 5 AND user = 1 AND date = x) AS five 
FROM table 
WHERE user = 1

到目前为止,我的查询速度非常快,但是当有更多记录时,我担心五个以上子查询的含义。

出于好奇,这样一个带有五个子查询的查询是否比五个单独的查询具有性能优势/劣势?我假设它更快,因为它只是一次访问数据库而不是 5 次?

编辑:有一个大约 60 条记录的表 2,用于对表 1 中的数千条记录进行分类。表 2 中的每条记录都按 1 - 5 的类型值分类(这是我正在使用的对我想要总和的项目进行分组)。

【问题讨论】:

  • 为了[神名]的爱,请在以后的问题中使用您的真实表格和真实数据。这种对真实情况的简化实际上并没有让你更快地得到正确的答案。很多时候,它只会给你一个错误的答案,除了你自己之外没有任何人的错。
  • 是的,我注意到了。再次感谢您的时间和帮助。

标签: mysql performance query-optimization subquery


【解决方案1】:
  1. 使用 ANSI 联接
  2. 您最好以 PIVOT 形式编写查询,如下面的查询

重写:

SELECT t.user, 
SUM(CASE table2.type WHEN 1 then amount else 0 end) As one,
SUM(CASE table2.type WHEN 2 then amount else 0 end) As two,
SUM(CASE table2.type WHEN 3 then amount else 0 end) As three,
SUM(CASE table2.type WHEN 4 then amount else 0 end) As four,
SUM(CASE table2.type WHEN 5 then amount else 0 end) As five
FROM table t
INNER JOIN table2 t2 ON t.table2_id = t2.id 
WHERE t.user = 1
  AND table2.type in (1,2,3,4,5)

我了解您的查询是伪查询,但它有一个挂起的 WHERE user 没有 FROM 子句。至于性能,上面一口气通过了表格。 5x 子查询表单需要 5 次通过,但如果有适当的索引可用,速度应该不会明显变慢。

【讨论】:

    【解决方案2】:

    您只需要一次查询即可获得每种类型的总和:

    SELECT 
      t2.type, 
      SUM(t.amount) 
    FROM 
      table t 
    INNER JOIN 
      table2 t2 
    ON 
      t.table2_id = t2.id 
    AND 
      t.user = 1
    AND 
      t.date = x 
    GROUP BY 
      t2.type
    

    【讨论】:

    • 谢谢丹!抱歉,当我问这个问题时,我过度简化了我的查询,并忽略了我要加入的第二个表的重要存在。“类型”属于表 2,而我得到的值是属于的总和到表 1。我在问题的编辑中注意到了这一点。
    • 这并没有改变任何东西,仍然只是一个使用 GROUP BY 的查询
    • 没有人应该要求这样做。 SQL 的目的是为应用程序检索数据,而不是以某种特定方式对其进行格式化以进行显示。
    • Nobody should ever require that 一个非常有力的声明。有报告引擎,例如 Crystal,需要您的数据在一行中。从行中操作它有点不太容易。这只是我想到的first
    【解决方案3】:

    好吧。如果这仅适用于一个用户,并且您绝对不需要按该顺序使用它....您可以做这样的事情..

    select user, type, sum(amount)
    where user = 1
    and date = x
    and type between (1,5)
    group by user, type
    

    这会给你

    1,1,sum
    1,2,sum
    1,3,sum
    1,4,sum
    1,5,sum
    

    而不是

    1,sum1,sum2,sum3,sum4,sum5
    

    这应该足以满足您的需要,我怀疑没有任何麻烦。

    【讨论】:

    • 嘿,谢谢乔迪。这有效(并且在您发布此问题后对我的问题进行了编辑)。您是对的,因为我正在为一位用户执行此操作,这应该可以正常工作。我不知道为什么我没想到。再次感谢:)
    • 如果您为任意数量的用户或表中的所有用户执行此操作,它将起作用。这就是他按用户和类型分组的原因。
    猜你喜欢
    • 1970-01-01
    • 2012-01-01
    • 2011-04-10
    • 2015-03-25
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多