动态数据透视语句中的条件聚合

Conditional Aggregation within Dynamic Pivot Statement

我有 2 个表说:

Orders:
id | Name | Amount | Date
1  | ABC  | 100    | 2020-10-01
2  | XYZ  | 200    | 2020-10-01
3  | MNO  | 250    | 2020-11-01

Order_details:
id | Item | Qty
1  | A    | 2
1  | B    | 1
1  | C    | 3
2  | X    | 1
3  | A    | 4

现在我想使用下订单的日期获取数据。

如果我想获取 2020-10-01 的数据,输出应该是这样的:

id | Name | Amount | Date       | Item1 | Qty | Item2 | Qty ...
1  | ABC  | 100    | 2020-10-01 | A     | 2   | B     | 1
2  | XYZ  | 200    | 2020-10-01 | X     | 1

我尝试使用子查询获取它,但我不确定如何打印该数据。

提前致谢!

对于每个订单固定的最大商品数量,您可以使用 window 函数和条件聚合:

select o.*,
    max(case when od.rn = 1 then item end) item1,
    max(case when od.rn = 1 then qty  end) qty1,
    max(case when od.rn = 2 then item end) item2,
    max(case when od.rn = 2 then qty  end) qty2,
    max(case when od.rn = 3 then item end) item3,
    max(case when od.rn = 3 then qty  end) qty3
from orders o
inner join (
    selet od.*, row_number() over(partition by id order by item) rn
    from order_details od
) od on od.id = o.id
group by o.id

您可以使用更多条件表达式扩展 select 子句,以处理每个订单 3 件以上的商品。

请注意,window 函数仅在 MySQL 8.0 中可用。

您可以在动态数据透视语句中使用条件聚合,它甚至适用于数据库版本 5.5

SET SESSION group_concat_max_len = 18446744073709551615;
SET @sql = NULL;
SET @date = '2020-10-01';

SELECT GROUP_CONCAT(
           DISTINCT
             CONCAT(
                    'MAX(CASE WHEN rn = ', rn,' THEN Item END ) AS Item', rn,
                    ', MAX(CASE WHEN rn = ', rn,' THEN Qty END ) AS Qty'
                    )
       )
  INTO @sql
  FROM ( 
        SELECT *, @rn := IF(@i = id, @rn + 1, 1) AS rn, @i := id
          FROM Order_details
          JOIN (SELECT @i := 0, @rn := 0) i
         ORDER BY id, Item
  ) od;

SET @sql = CONCAT('SELECT o.id, o.name, o.amount, o.date,',@sql,
                   ' FROM Orders o
                     JOIN (
                           SELECT *, @rn := IF(@i = id, @rn + 1, 1) AS rn, @i := id
                             FROM Order_details
                             JOIN (SELECT @i := 0, @rn := 0) i
                            ORDER BY id, Item    
                          ) od
                       ON od.id = o.id
                    WHERE o.date = "',@date,'"
                    GROUP BY o.id, o.name, o.amount, o.date
                    ORDER BY o.id');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

其中参数值可能会在第二行 (SET @date = '2020-10-01';) 内更新。顺便说一句,函数 GROUP_CONCAT() 有一个长度上限( 对于参数 group_concat_max_len,默认值为 1024)可能会被更新(对于当前会话的最大值 18446744073709551615) table 有多个不同的项目,因此有很多列。

Demo