【问题标题】:MySQL - SELECT AVG on some rows and SUM on allMySQL - 在某些行上选择 AVG,在所有行上选择 SUM
【发布时间】:2026-02-09 00:55:01
【问题描述】:

我正在尝试对某些特定行的值求平均值,但对所有行的数量求和。

我有两张桌子,一张叫exchanges,另一张叫valid_country

交流

+-----------+----------+--------------+----------+--------+
|     id    |   ref    |     country  |   value  | volume |
+-----------+----------+--------------+----------+--------+
|     1     |  1029    |      DE      |   1 000  |   100  |
+-----------+----------+--------------+----------+--------+
|     2     |  1029    |      US      |   2 000  |   250  |
+-----------+----------+--------------+----------+--------+
|     3     |  1029    |      FR      |   3 500  |   300  |
+-----------+----------+--------------+----------+--------+
|     4     |  1053    |      UK      |   1 200  |   110  |
+-----------+----------+--------------+----------+--------+
|     5     |  1029    |      RU      |     900  |    70  |
+-----------+----------+--------------+----------+--------+

此表包含许多具有不同国家/地区的参考文献 (ref),它们本身具有不同的值和数量。

有效国家

+--------------+--------------+
|     ref      |   country    |
+--------------+--------------+
|    1029      |     US       |
+--------------+--------------+
|    1029      |     RU       |
+--------------+--------------+
|    1053      |     UK       |
+--------------+--------------+

此表列出了所有可以取平均值的“良好”国家/地区。

我想要的结果查询是:

+----------+------------+-------------+
|   ref    | AVG(value) | SUM(volume) |
+----------+------------+-------------+
|  1029    |    1 450   |     720     |
+----------+------------+-------------+
|  1053    |    1 200   |     110     |
+----------+------------+-------------+

首先参考是GROUP BY。 参考 1029 应 AVERAGE 仅美国和俄罗斯的值(因为表 valid_country)但 SUM 所有国家的体积。 Ref 1053 也是如此,但由于只有一排,所以很容易。

这里有一点Fiddle。 SQL 请求是错误的,因为它平均了所有国家,而不仅仅是好的国家。

【问题讨论】:

  • 首先,您需要加入您的两个表,以便在您的查询中知道哪些国家/地区被认为是“好”。
  • (顺便说一句,您的小提琴将第二个表的值插入到第一个表中。由于第一个表也包含这些列,因此它不会引发错误,但不会给出一个实际可测试的结果。)
  • @CBroe 谢谢!我已经编辑了我的小提琴:sqlfiddle.com/#!9/e16969/4

标签: mysql sql group-by sum average


【解决方案1】:

您可以使用LEFT JOINCASE 语句忽略AVG (SQLFiddle) 中的某些值:

SELECT e.ref,
       AVG(CASE WHEN vc.country IS NOT NULL THEN e.value END) AS average,
       SUM(e.volume) AS volume
FROM exchanges e
LEFT JOIN valid_country vc ON ( vc.country = e.country )
GROUP BY e.ref

CASEreturns NULL如果不匹配,AVG 会忽略这些值:

|  ref | average | volume |
|------|---------|--------|
| 1029 |    1450 |    720 |
| 1053 |    1200 |    110 |

【讨论】:

  • 谢谢。这很好用!在我的大型数据库上比较您的查询和 Nico Weisenauer 的查询,以检查哪个更快。我会在测试后给出答案。
【解决方案2】:

你可以通过在mysql的聚合函数中使用case语句来实现。Demo

SELECT e.ref,e.country , AVG(case when c.country = e.country then e.value end) as avge,SUM(volume)
FROM exchanges e left join valid_country as c on e.country = c.country
GROUP BY e.ref

【讨论】:

    【解决方案3】:

    此查询使用子查询来提供正确的结果:

    SELECT e1.ref,subq.avg,SUM(volume)
    FROM exchanges e1,
     (SELECT e2.ref, AVG(value) as avg 
      FROM exchanges e2, valid_country vc
      WHERE e2.country = vc.country
      GROUP BY e2.ref) as subq
    WHERE e1.ref = subq.ref
    GROUP BY ref
    

    【讨论】:

    • 谢谢。这很好用!在我的大型数据库中比较您的查询和 Peter Lang 的查询,以检查哪个更快。我会在测试后给出答案。
    【解决方案4】:

    我认为与valid_country 的比较需要同时使用refcountry

    SELECT e.ref,
           AVG(CASE WHEN vc.country IS NOT NULL THEN e.value END) AS average,
           SUM(e.volume) AS volume
    FROM exchanges e LEFT JOIN
         valid_country vc
         ON vc.country = e.country AND vc.ref = e.ref
    GROUP BY e.ref;
    

    这对您的示例数据无关紧要,但对于更大的问题可能很重要。

    【讨论】:

    • 好森戈登。这确实是我需要的完整比较。