【问题标题】:Using join and group with sum将 join 和 group 与 sum 一起使用
【发布时间】:2021-04-03 03:09:53
【问题描述】:

我对@9​​87654321@ 还很陌生,我遇到了这个理论问题。我得到了这些tables

customers
---------------
id
name
country
order_date


orders
---------------
id
order_number
order_type

customers_order_details
---------------
id
customer_id
order_id
price

一个客户可以有多个不同的订单。我需要检索总价最高的客户,总价必须至少为 100。我的方法是否正确?

SELECT c.id, c.name AS customer_name, c.country , SUM(d.price) AS total_price
FROM customers c
JOIN customers_order_details d 
    ON c.id = d.customer_id
GROUP BY customer_name, 
HAVING total_price >= 100
ORDER BY total_price DESC;

由于我被告知 GROUP BY 我需要添加所有指定的 columns 但我觉得使用该名称绰绰有余

【问题讨论】:

    标签: mysql sql inner-join aggregate-functions having-clause


    【解决方案1】:

    您的代码看起来相当不错。我只建议按客户表的主键而不是名称进行聚合:

    SELECT c.id, c.name AS customer_name, c.country , SUM(d.price) AS total_price
    FROM customers c
    JOIN customers_order_details d ON c.id = d.customer_id
    GROUP BY c.id
    HAVING SUM(d.price) >= 100
    ORDER BY total_price DESC;
    

    这使代码成为有效的聚合查询; select 子句中的所有非聚合列在功能上都依赖于 group by 子句中的列。

    附带说明:在HAVING 子句中使用列别名是对 SQL 标准的 MySQL 扩展。您可以使用该功能,或者在纯 ANSI SQL 中使用 HAVING 子句,重复聚合表达式。

    【讨论】:

    • 感谢您的意见!如果我要使用指定的所有其他列,是否有警告?比如使用 c.country、c.name 和 c.id?
    • @user_2.177: c.idc 的主键,因此您可以将该表中您喜欢的任何列放在select 子句中:它们是功能依赖于 id,因此无需将它们放在group by 子句中(这将是多余的)。见:dev.mysql.com/doc/refman/8.0/en/…
    【解决方案2】:

    看起来几乎是正确的。

    只按customers.name 分组是不对的。除此之外,这会在配置更紧密的 MySQL 服务器或更新版本甚至来自其他供应商的 DBMS 上引发错误,如果有两个或多个不同的客户具有相同的名称,例如“John Smith”,会发生什么情况?他们都聚集在同一组中,给出了错误的数字!

    最安全的选择是按所有不作为聚合函数参数的列进行分组。在这种情况下,这将是 customers.idcustomers.namecustomers.country。在某些 DBMS 中,您还可以仅按列的元组对所有未提供给聚合函数的列所依赖的列进行分组。如果customers.id 被声明为主键,那将满足该规则,您可以按它进行分组。但我不确定 MySQL 是否确实实现了该快捷方式或在哪些版本或配置中实现。所以你最好把这里的所有列都看一遍。

    旁注:架构设计有点奇怪。为什么订单明细直接关联到客户,而不是订单本身关联到客户?因为现在一个订单可以有多个属于不同客户的详细信息。这在您的用例中可能是正确的,但这不是您所期望的通常情况。也许你应该修改一下。

    【讨论】:

    • 感谢您的建议!就您所说的而言,customer.idcustomers 表中的主键,但在customer_order_details 中是外键。使用customer.id 仍然足够吗?
    • @user_2.177:您在聚合函数之外选择的所有列都取决于id,因为它们都来自customers。就像我说的,如果您的 DBMS 实现了该捷径,那么是的,按 id 分组就足够了。不过,安全且更便携的方法是按所有列分组。
    猜你喜欢
    • 2010-10-06
    • 2014-05-26
    • 1970-01-01
    • 2015-08-21
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 2020-04-28
    • 2014-01-12
    相关资源
    最近更新 更多