【问题标题】:Mysql Sum or Group concat base on distinct idMysql Sum 或 Group_concat 基于不同的 id
【发布时间】:2018-05-31 19:06:31
【问题描述】:

我确定有人已经在某个地方问过这个问题,但似乎找不到。

在 mysql 中是否可以将 sum 或 group concat (AGGREGATE FUNCTION) 与 distinct 结合起来?

示例:我有一个订单产品,它可以有很多选择和很多受益人。如何在一个查询中(不使用子查询)获取期权列表、期权价格总和和受益人列表?

我已经构建了一个样本数据集:

CREATE TABLE `order`
(id INT NOT NULL PRIMARY KEY);

CREATE TABLE order_product 
(id INT NOT NULL PRIMARY KEY
,order_id INT NOT NULL
);
CREATE TABLE order_product_options 
(id INT NOT NULL PRIMARY KEY
,title VARCHAR(20) NOT NULL
,price INT NOT NULL
,order_product_id INT NOT NULL
);

CREATE TABLE order_product_beneficiary 
(id INT NOT NULL PRIMARY KEY 
,name VARCHAR(20) NOT NULL
,order_product_id INT NOT NULL
);

INSERT INTO `order` (`id`) VALUES (1);
INSERT INTO `order_product` (`id`, `order_id`) VALUES (1, 1);
INSERT INTO `order_product_options` (`id`, `title`, `price`, `order_product_id`) 
VALUES  (1,'option1', 1, 1), (2, 'option2', 2, 1), (3, 'option3', 3, 1), (4, 'option3', 3, 1);

INSERT INTO `order_product_beneficiary` (`id`, `name`, `order_product_id`) 
VALUES  (1,'mark', 1), (2, 'jack', 1), (3, 'jack', 1);

http://sqlfiddle.com/#!9/37e383/2

我想要的结果是

  1. id: 1
  2. 选项:选项1、选项2、选项3、选项3
  3. 期权价格:9
  4. 受益人:马克、杰克、杰克

在不使用子查询的情况下,这在 mysql 中是否可行? (我知道在 oracle 中是可能的) 如果可以,你会怎么做?

谢谢

【问题讨论】:

  • 为什么jack 重复了?此外,如果您可以编辑您的帖子以包含示例数据,那将是更可取的。这将使问题更具可读性并增加获得正确答案的可能性。
  • 您将数据检索问题与数据显示问题混为一谈。首先返回正确的结果。然后我们可以讨论以合适的方式格式化它的方法。 (返回选项和每个选项的数量会不会更有意义?)
  • 对于数据,我放了一个js小提琴,我复制了jack,只是作为一个例子,因为我想根据id而不是字段的值来使用distinct。

标签: mysql sql distinct aggregate-functions


【解决方案1】:

根据您的描述,我认为您只需要 DISTINCT 中的 GROUP_CONCAT()。但是,由于重复,这将不起作用(如评论中所述,但不是问题)。

一种解决方案是在结果中包含 id:

SELECT op.id,
       GROUP_CONCAT(DISTINCT opo.title, '(', opo.id, ')' SEPARATOR ', ') AS options,
       SUM(opo.price) AS options_price,
       GROUP_CONCAT(DISTINCT opb.name, '(', opb.id, ')' SEPARATOR ', ') AS 'beneficiaries'
FROM order_product op INNER JOIN
      order_product_options opo
      ON opo.order_product_id = op.id INNER JOIN
      order_product_beneficiary opb 
      ON opb.order_product_id = op.id
GROUP BY op.id;

这并不完全是您的结果,但可能就足够了。

编辑:

哦,我明白了。您正在加入两个不同的维度并获得笛卡尔积。解决方案是在加入之前聚合:

SELECT op.id, opo.options, opo.options_price,
       opb.beneficiaries
FROM order_product op INNER JOIN
     (SELECT opo.order_product_id,
             GROUP_CONCAT(opo.title SEPARATOR ', ') AS options,
             SUM(opo.price) AS options_price
      FROM order_product_options opo
      GROUP BY opo.order_product_id
     ) opo
     ON opo.order_product_id = op.id INNER JOIN
     (SELECT opb.order_product_id,
             GROUP_CONCAT(opb.name SEPARATOR ', ') AS beneficiaries
      FROM order_product_beneficiary opb 
      GROUP BY opb.order_product_id
     ) opb
     ON opb.order_product_id = op.id;

Here 是 SQL Fiddle。

【讨论】:

  • 谢谢!!这就是我想要的!!
【解决方案2】:

有点像,在内部查询中进行价格求和,然后加入order_product 表。

SELECT 
    op.id,
    MAX(opo.title) AS 'options',
    MAX(opo.price) AS 'options price',
    GROUP_CONCAT(opb.name SEPARATOR ', ') AS 'beneficiaries'
FROM
    order_product op
INNER JOIN (
    SELECT order_product_id, SUM(price) price, GROUP_CONCAT(title SEPARATOR ', ') title
    FROM order_product_options
    GROUP BY order_product_id 
) opo ON opo.order_product_id = op.id
INNER JOIN order_product_beneficiary opb ON opb.order_product_id = op.id
GROUP BY op.id

Demo

【讨论】:

    猜你喜欢
    • 2018-07-20
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2020-05-23
    • 1970-01-01
    • 2015-05-26
    • 2011-12-01
    相关资源
    最近更新 更多