【问题标题】:How can I GROUP BY in conjunction with a JOIN?如何将 GROUP BY 与 JOIN 结合使用?
【发布时间】:2019-05-25 15:48:20
【问题描述】:

我正在尝试从一个表中的列中获取值,并将它们与另一个表中多个列的最大值组合在一起,其中第一个表的值作为外键多次出现。我还需要将 SELECT 返回的出现次数限制为 1。

我的(简化的)表格如下所示:

名称:
+--+------+
|PK|姓名|
+--+------+
| 1|弗雷德|
| 2|鲍勃|
| 3|乔治|
+--+------+
价值观:
+--+----+----+----+--+
|PK|val1|val2|val3|FK|
+--+----+----+----+--+
| 1| 1| 2| 5| 2|
| 2| 2| 0| 2| 1|
| 3| 1| 1|空| 1|
| 4| 7| 0|空| 2|
| 5| 0| 3| 3| 3|
| 6| 5| 2| 2| 3|
| 7| 6| 3| 0| 1|
| 8| 1| 2| 5| 3|
| 9| 0| 2|空| 2|
+--+----+----+----+--+

我目前的要求是:

SELECT Name.name, GREATEST(Vals.val1, COALESCE(val2, 0), COALESCE(val3, 0))
    FROM Name INNER JOIN (Vals) ON Name.PK = Vals.FK;

目的是获取每个名称出现的最大值。结果应如下所示: 最大值:

+------+---+
|名称|最大|
+------+----+
|弗雷德| 6|
|鲍勃| 7|
|乔治| 5|
+--------+---+

但目前我看到的是:

+------+---+
|名称|最大|
+------+----+
|弗雷德| 2|
|弗雷德| 1|
|弗雷德| 6|
|鲍勃| 5|
|鲍勃| 7|
|鲍勃| 2|
|乔治| 3|
|乔治| 5|
|乔治| 5|
+--------+---+

我在哪里获得每次出现的名称键的平均值。我不确定是否需要 'WHERE' 或 'GROUP BY' 来解决这个问题,但每次我都尝试过时,我都会遇到错误。例如:

SELECT Name.name, GREATEST(Vals.val1, COALESCE(val2, 0), COALESCE(val3, 0))
    FROM Name INNER JOIN (Vals) ON Name.PK = Vals.FK GROUP BY Name.name;

SELECT Name.name, GREATEST(Vals.val1, COALESCE(val2, 0), COALESCE(val3, 0)) WHERE Vals.FK = Name.PK
    FROM Name INNER JOIN (Vals) ON Name.PK = Vals.FK;

【问题讨论】:

  • 这种问题可能是设计不佳的症状。任何时候你发现自己有枚举的列名(例如,2),警钟应该开始响起。也就是说,MAX(GREATEST...) ... GROUP BY 应该可以解决您的问题
  • 由于任务的性质,这些值对应于每个需要跟踪的离散事件(想想每个人进行科学实验时的值)。根据说明,每个值必须以上述方式记录在同一张表中。我很乐意听取如何根据我自己的知识改进设计,但不幸的是,这是不可避免的。
  • 通常,您会将值表一分为二。让我们假设它是一张订单表。因此,一张表将保存 order_id 和 customer_id,而另一张表将保存所订购商品的详细信息,可能是 order_id、item_id、数量。看?每个项目都有自己的行;不是它自己的列。
  • 顺便说一句,我怀疑你在这里需要 COALESCE。
  • 是的,这就是我认为在更实际的情况下会去的地方。在这种情况下是否有替代 COALESCE 来忽略 NULL 的方法?在此之前,The GREATEST 在它们所在的任何行上都返回 NULL。如果有帮助,数据类型是 TINYINT UNSIGNED。

标签: mysql sql


【解决方案1】:

将多行减少为每个组的单个值是通过聚合函数来实现的,例如MAX:

SELECT Name.name,
       MAX(GREATEST(Vals.val1, COALESCE(val2, 0), COALESCE(val3, 0))) max
  FROM Name
  INNER JOIN (Vals) ON Name.PK = Vals.FK
  GROUP BY Name.name;

【讨论】:

  • 这样做会导致错误 1140 (42000):在没有 GROUP BY 的聚合查询中,SELECT 列表的表达式 #1 包含非聚合列 'database.Name.name';这与 sql_mode=only_full_group_by 不兼容
  • without GROUP BY 是什么意思 - 您是否列出了 SELECT 中在 MAX 之外的所有列也在 GROUP BY 中?在您的示例中,只有 1 个这样的列“Name.name”,但在您的实际查询中可能还有更多...
  • 我仔细看了看,刚刚打错了更正,现在效果很好。非常感谢!
猜你喜欢
  • 2021-12-10
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多