【问题标题】:MySQL - aggregating and GROUP BY with subqueriesMySQL - 聚合和 GROUP BY 与子查询
【发布时间】:2020-04-09 17:21:00
【问题描述】:

是否可以使用 GROUP BY 来聚合带有子查询的单元格?我正在使用的数据库包含客户订单信息(订单 ID、名称、地址、产品、选项等)。当客户为产品选择多个选项时,它们会显示在不同的行中。我需要通过将所有产品选项映射到新列来将它们聚合到同一行,但由于我有子查询,因此不确定在哪里添加 GROUP BY...

这是查询: http://sqlfiddle.com/#!9/83a399/4/0

预期输出:

Order ID | Qty | Option | Size | Product | Ref
-----------------------------------------------
12345    | 1   | R      | L    | Tee     | R / Tee L
12346    | 2   | Bl     | S    | Hood    | 2x Bl / Hood S

【问题讨论】:

  • 你的预期输出是什么?
  • @forpas 刚刚添加,抱歉。

标签: mysql group-by case aggregates


【解决方案1】:

GROUP BY 具有唯一键的列和其余的 zse aggregation functions 在您的情况下像 MAX

SELECT 
    `Order ID`, 
    `Qty`, 
    MAX(`Option`), 
    MAX(`Size`),
    `Product`,
        MAX(CONCAT (
            CASE 
                WHEN `Qty` > 1
                THEN CONCAT (`Qty`, 'x ')
                ELSE ''
                END,
            `Option`,
            ' / ',
            `Product`,
            CASE
                WHEN COALESCE (`Size`, '') != ''
                THEN CONCAT ('  ', `Size`)
                ELSE ''
                END
                ))
                AS `Ref`
    FROM (

        SELECT
            `order`.`order_id` AS `Order ID`,
            `order_product`.`quantity` AS `Qty`,

            CASE
                WHEN `order_option`.`value` LIKE '%Red%' THEN  'R'
                WHEN `order_option`.`value` LIKE '%Blue%' THEN  'Bl'
            END AS `Option`,

            CASE
                WHEN `order_product`.`name` LIKE '%t-shirt%' THEN 'Tee'
                WHEN `order_product`.`name` LIKE '%hoodie%' THEN 'Hood'
                ELSE `order_product`.`name`
            END AS `Product`,

            CASE        
                WHEN `order_option`.`value` LIKE '%Small%' THEN 'S'
                WHEN `order_option`.`value` LIKE '%Medium%' THEN  'M'
                WHEN `order_option`.`value` LIKE '%Large%' THEN  'L'

                ELSE ''
            END AS `Size`

    FROM
        `order`,
        `order_product`,
        `order_option`

    WHERE
        `order`.`order_id` = `order_option`.`order_id` AND 
        `order_product`.`order_product_id` = `order_option`.`order_product_id`

    ORDER BY `order`.`order_id` ASC

                ) AS `Orders`
 GROUP BY     
     `Order ID`, 
    `Qty`,
    `Product` ;

http://sqlfiddle.com/#!9/83a399/6

【讨论】:

  • 我刚刚尝试过,但出现此错误:#1055 - SELECT 列表的表达式 #21 不在 GROUP BY 子句中,并且包含在功能上不依赖于的非聚合列“Orders.Option” GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容
  • 您的查询中没有orders.option,所以您更改了查询,
  • 即使dbfiddle.uk/… 没有显示错误,它已启用完整分组
  • 解决了这个问题。我需要从 sql 模式禁用 ONLY_FULL_GROUP_BY。
【解决方案2】:

您必须group by Order ID 并聚合:

SELECT 
  `Order ID`, 
  MAX(`Qty`) AS `Qty`, 
  MAX(`Option`) AS `Option`, 
  MAX(`Size`) AS `Size`,
  MAX(`Product`) AS `Product`,
  CONCAT_WS(' ',  
    MAX(CONCAT(
      CASE WHEN `Qty` > 1 THEN CONCAT(`Qty`, 'x ') ELSE '' END,
      `Option`, ' / ', `Product`,
      CASE WHEN COALESCE(`Size`, '') != '' THEN CONCAT('  ', `Size`) ELSE '' END
    )),
    MAX(`Size`)
  ) AS `Ref`
FROM (
  SELECT  
    o.`order_id` AS `Order ID`,
    op.`quantity` AS `Qty`,
    CASE 
      WHEN oo.`value` LIKE '%Red%' THEN  'R'
      WHEN oo.`value` LIKE '%Blue%' THEN  'Bl'
    END AS `Option`,
    CASE
      WHEN op.`name` LIKE '%t-shirt%' THEN 'Tee'  
      WHEN op.`name` LIKE '%hoodie%' THEN 'Hood'
      ELSE op.`name`
    END AS `Product`,
    CASE
      WHEN oo.`value` LIKE '%Small%' THEN 'S'
      WHEN oo.`value` LIKE '%Medium%' THEN  'M'
      WHEN oo.`value` LIKE '%Large%' THEN  'L'
      ELSE ''
    END AS `Size`
  FROM `order` AS o
  INNER JOIN `order_option` AS oo ON o.`order_id` = oo.`order_id`
  INNER JOIN `order_product` AS op ON op.`order_product_id` = oo.`order_product_id`
) AS `Orders`
GROUP BY `Order ID`
ORDER BY `Order ID` DESC

我对您的代码进行了更改,例如为表使用正确的连接和别名。
请参阅demo
结果:

| Order ID | Qty | Option | Size | Product | Ref            |
| -------- | --- | ------ | ---- | ------- | -------------- |
| 12346    | 2   | Bl     | S    | Hood    | 2x Bl / Hood S |
| 12345    | 1   | R      | L    | Tee     | R / Tee L      |

【讨论】:

  • 是否可以在查找表中使用JOIN 而不是使用CASE 语句?例如,我有一个存储所有产品缩写的表。 JOIN 只会返回表格第二列的缩写。
  • 我不知道你的设计,所以我不知道。但如果效率很重要,则连接的效率远低于 CASE 表达式。
  • 好的。甚至用他们的 2 个字符的缩写来替换像美国州这样的东西? (例如德克萨斯州 -> TX)。
  • 如果您指的是我提到的效率,那么效率较低的不是值,而是连接。但是,如果您需要进行这种更改,那么无论如何您都应该这样做。发布一个问题,您将在其中展示您的设计以及示例数据和预期结果。
  • 检查这个:db-fiddle.com/f/eDxcjp7VNgdR1t3vhkdRoe/1 虽然我不确定这是否适合你的设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 2014-11-22
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
相关资源
最近更新 更多