Dynamic Pivot 语句中的条件聚合
Posted
技术标签:
【中文标题】Dynamic Pivot 语句中的条件聚合【英文标题】:Conditional Aggregation within Dynamic Pivot Statement 【发布时间】:2021-02-16 04:55:48 【问题描述】:我有 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
我尝试使用子查询来获取它,但我不确定如何打印该数据。
提前致谢!
【问题讨论】:
PIVOT 在 mysql 中没有实现。 订单名称是否总是三个字母的字符串? 为什么是子查询? @SlavaRozhnev 不,它将包含订购人的姓名。举个例子,我写了一个 3 个字母的字符串。 @Strawberry 我的方法是使用子查询。任何其他方法也适用于我。 【参考方案1】:对于每个订单的固定最大商品数量,您可以使用窗口函数和条件聚合:
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 件商品。
请注意,窗口函数仅在 MySQL 8.0 中可用。
【讨论】:
这里的问题是项目的数量也可以增加到 10 个。我们对每个订单的商品数量没有限制。【参考方案2】:您可以在动态枢轴语句中使用条件聚合,它甚至适用于数据库版本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
) 对于当前会话的情况,表有多个不同的项目,因此有很多列。
Demo
【讨论】:
谢谢,这在一开始对我有用,但现在它显示了一些语法错误。我没有更改此查询中的任何内容。SQL Error [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM Orders o JOIN ( ' at line 1
嗨@MdAkramKazmi,不客气。您能在演示中展示您遇到错误的案例吗?
解决了这个问题,当 order_details 表中有超过 11 个特定 ID 的条目时,查询不起作用。已在演示中更新。
@MdAkramKazmi 那么您需要增加参数 group_concat_max_len
的值。请查看更新后的答案。以上是关于Dynamic Pivot 语句中的条件聚合的主要内容,如果未能解决你的问题,请参考以下文章