【问题标题】:Is there a way to combine two aggregate functions in MySQL to get distinct values?有没有办法在 MySQL 中结合两个聚合函数来获得不同的值?
【发布时间】:2016-03-22 07:03:53
【问题描述】:

我在 MySQL 中有以下架构:

CREATE TABLE `ORDER_CONTENTS` (
  `Order_ID` int(10) NOT NULL,
  `Pizza_Name` varchar(20) NOT NULL DEFAULT '',
  `Quantity` int(2) NOT NULL,
  PRIMARY KEY (`Order_ID`,`Pizza_Name`),
  KEY `ordercontentsfk2_idx` (`Pizza_Name`),
  CONSTRAINT `order_contentsfk1` FOREIGN KEY (`Order_ID`) REFERENCES `ORDERS` (`Order_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `CUSTOMERS` (
  `Mobile_Number` varchar(10) NOT NULL,
  `Name` varchar(45) NOT NULL,
  `Age` int(3) DEFAULT NULL,
  `Gender` enum('M','F') DEFAULT NULL,
  `Email` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`Mobile_Number`),
  UNIQUE KEY `Mobile_Number_UNIQUE` (`Mobile_Number`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `ORDERS` (
  `Order_ID` int(10) NOT NULL AUTO_INCREMENT,
  `Mobile_Number` varchar(10) NOT NULL,
  `Postcode` int(4) NOT NULL,
  `Timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`Order_ID`),
  KEY `ordersfk1_idx` (`Mobile_Number`),
  KEY `ordersfk2_idx` (`Postcode`),
  CONSTRAINT `ordersfk1` FOREIGN KEY (`Mobile_Number`) REFERENCES `CUSTOMERS` (`Mobile_Number`) ON DELETE NO ACTION ON UPDATE CASCADE,
  CONSTRAINT `ordersfk2` FOREIGN KEY (`Postcode`) REFERENCES `STORES` (`Postcode`) ON DELETE NO ACTION ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

CREATE TABLE `STORES` (
  `Postcode` int(4) NOT NULL DEFAULT '0',
  `Address` varchar(100) DEFAULT NULL,
  `Phone_Number` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`Postcode`),
  UNIQUE KEY `Postcode_UNIQUE` (`Postcode`),
  UNIQUE KEY `Address_UNIQUE` (`Address`),
  UNIQUE KEY `Phone_Number_UNIQUE` (`Phone_Number`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我需要找到以下内容:

问题陈述

为每位顾客列出他们最喜欢的披萨店的详细信息 商店,其中一家商店是最喜欢的,如果它是 顾客购买的比萨饼最多)。

我已经设法弄清楚以下查询:

select `Name`,SUM(quantity) as hqty,COUNT(*),Postcode from CUSTOMERS natural join orders natural join order_contents group by Mobile_Number,postcode;

这给了我如下结果:

+---------------+------+----------+----------+
| Name          | hqty | COUNT(*) | Postcode |
+---------------+------+----------+----------+
| Homer Simpson |   19 |        3 |     4000 |
| Homer Simpson |    1 |        1 |     4502 |
| Ned Flanders  |    2 |        1 |     4000 |
+---------------+------+----------+----------+

但在这种情况下,同一客户有两个实例(即 Homer Simpson)。为什么会这样?我想我需要使用聚合函数的组合。

任何帮助/解释都会很棒。

干杯!

[更新 1] 仅供参考:

select * from CUSTOMERS natural join orders natural join 订单内容;

上面的查询产生这个:

+----------+---------------+---------------+------+--------+-----------------+----------+---------------------+--------------+----------+
| Order_ID | Mobile_Number | Name          | Age  | Gender | Email           | Postcode | Timestamp           | Pizza_Name   | Quantity |
+----------+---------------+---------------+------+--------+-----------------+----------+---------------------+--------------+----------+
|        1 | 0412345678    | Homer Simpson |   38 | M      | homer@doh.com   |     4000 | 2014-08-21 19:38:01 | Garlic Bread |        9 |
|        1 | 0412345678    | Homer Simpson |   38 | M      | homer@doh.com   |     4000 | 2014-08-21 19:38:01 | Hawaiian     |        9 |
|        2 | 0412345678    | Homer Simpson |   38 | M      | homer@doh.com   |     4000 | 2014-08-21 19:38:01 | Vegan Lovers |        1 |
|        3 | 0412345678    | Homer Simpson |   38 | M      | homer@doh.com   |     4502 | 2014-08-21 19:38:12 | Meat Lovers  |        1 |
|        4 | 0412345679    | Ned Flanders  |   60 | M      | ned@vatican.net |     4000 | 2014-08-21 19:39:09 | Meat Lovers  |        2 |
+----------+---------------+---------------+------+--------+-----------------+----------+---------------------+--------------+----------+

另外请注意问题陈述

【问题讨论】:

  • 您的客户有两个邮政编码......您的查询组按邮政编码......这是你的问题
  • 这就是问题的重点......请阅读问题说明

标签: mysql sql group-by aggregate-functions


【解决方案1】:
SELECT  *
FROM    customers c
JOIN    stores s
ON      s.postcode =
        (
        SELECT  postcode
        FROM    orders o
        JOIN    order_contents oc
        USING   (order_id)
        WHERE   o.mobile_number = c.mobile_number
        GROUP BY
                postcode
        ORDER BY
                SUM(quantity) DESC
        LIMIT 1
        )

这不会显示根本没有下订单的客户。如果您需要这些,请将 JOIN 更改为 storesLEFT JOIN

【讨论】:

    【解决方案2】:

    按您的客户主键(可能是 ID)分组。

    您获得重复客户的原因是您按 mobile_number 和邮政编码对查询进行分组,这没有建立唯一索引。

    您的查询应该是这样的:

    select Name ,SUM(quantity) as hqty,COUNT(*),Postcode from CUSTOMERS natural join orders natural join order_contents group by CUSTOMERS.id

    将 ID 替换为客户表 PK 的任何内容,并且它应该由客户唯一分组。

    【讨论】:

    • mobile_number 是 CUSTOMER 表的主键:\
    • 然后尝试按电话号码分组
    • 哦,然后在总和上添加一个MAX() 函数,以仅获取数量最多的路线(订购的比萨饼最多)。应该是MAX(SUM(quantity)) as hqty
    • MySQL 由于某种原因不允许合并 MAX(SUM())。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 2011-02-23
    • 2011-10-14
    相关资源
    最近更新 更多