动态数据透视语句中的条件聚合
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 有多个不同的项目,因此有很多列。
我有 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 有多个不同的项目,因此有很多列。