无论顺序如何,计算多列值的唯一组合?
Counting unique combinations of values across multiple columns regardless of order?
我有一个 table 看起来有点像这样:
Customer_ID | Offer_1 | Offer_2 | Offer_3
------------|---------|---------|--------
111 | A01 | 001 | B01
222 | A01 | B01 | 001
333 | A02 | 001 | B01
我想编写一个查询来计算 table 中有多少独特的优惠组合,而不管优惠出现的顺序如何。
所以在上面的例子中有两个独特的组合:客户 111 和 222 都有相同的三个报价,所以他们算作一个独特的组合,然后客户 333 是唯一拥有他们拥有的三个订单的客户.所以查询的期望输出是 2.
对于一些额外的上下文:
- customer_ID列为整数格式,所有offer
列为 varchar 格式。
- 实际有12个offer列,超过300万行
table,报价列中有超过 100 个不同的值。我
简化了示例以更好地说明我正在尝试做的事情,但是任何解决方案都需要扩展到这个数量
可能的组合。
我可以将所有报价列连接在一起,然后 运行 计算结果的不同语句,但这不考虑具有相同唯一报价组合但订购方式不同的客户(例如上例中的客户 111 和 222)。
请问有人知道如何解决这个问题吗?
一种方法是将优惠 union all
放入一列,然后使用 select distinct listagg...
获取优惠组合。试试这个:
with u as
(select Customer_ID, Offer_1 as Offer from table_name union all
select Customer_ID, Offer_2 as Offer from table_name union all
select Customer_ID, Offer_3 as Offer from table_name)
select distinct listagg(Offer, ',') within group(order by Offer) from u
group by Customer_ID
假设字符 /
没有出现在任何报价名称中,您可以这样做:
select count(distinct offer_combo) as distinct_offers
from (
select listagg(offer, '/') within group (order by offer) as offer_combo
from (
select customer_id, offer_1 as offer from t
union all select customer_id, offer_2 from t
union all select customer_id, offer_3 from t
) x
group by customer_id
) y
结果:
DISTINCT_OFFERS
---------------
2
参见 db<>fiddle 中的 运行 示例。
没有UNION ALL的解决方案。它应该有更好的性能。
/*
WITH MYTAB (Customer_ID, Offer_1, Offer_2, Offer_3) AS
(
VALUES
(111, 'A01', '001', 'B01')
, (222, 'A01', 'B01', '001')
, (333, 'A02', '001', 'B01')
)
*/
SELECT COUNT (DISTINCT LIST)
FROM
(
SELECT LISTAGG (V.Offer, '|') WITHIN GROUP (ORDER BY V.Offer) LIST
FROM MYTAB T
CROSS JOIN TABLE (VALUES T.Offer_1, T.Offer_2, T.Offer_3) V (Offer)
GROUP BY T.CUSTOMER_ID
)
我有一个 table 看起来有点像这样:
Customer_ID | Offer_1 | Offer_2 | Offer_3
------------|---------|---------|--------
111 | A01 | 001 | B01
222 | A01 | B01 | 001
333 | A02 | 001 | B01
我想编写一个查询来计算 table 中有多少独特的优惠组合,而不管优惠出现的顺序如何。
所以在上面的例子中有两个独特的组合:客户 111 和 222 都有相同的三个报价,所以他们算作一个独特的组合,然后客户 333 是唯一拥有他们拥有的三个订单的客户.所以查询的期望输出是 2.
对于一些额外的上下文:
- customer_ID列为整数格式,所有offer 列为 varchar 格式。
- 实际有12个offer列,超过300万行 table,报价列中有超过 100 个不同的值。我 简化了示例以更好地说明我正在尝试做的事情,但是任何解决方案都需要扩展到这个数量 可能的组合。
我可以将所有报价列连接在一起,然后 运行 计算结果的不同语句,但这不考虑具有相同唯一报价组合但订购方式不同的客户(例如上例中的客户 111 和 222)。
请问有人知道如何解决这个问题吗?
一种方法是将优惠 union all
放入一列,然后使用 select distinct listagg...
获取优惠组合。试试这个:
with u as
(select Customer_ID, Offer_1 as Offer from table_name union all
select Customer_ID, Offer_2 as Offer from table_name union all
select Customer_ID, Offer_3 as Offer from table_name)
select distinct listagg(Offer, ',') within group(order by Offer) from u
group by Customer_ID
假设字符 /
没有出现在任何报价名称中,您可以这样做:
select count(distinct offer_combo) as distinct_offers
from (
select listagg(offer, '/') within group (order by offer) as offer_combo
from (
select customer_id, offer_1 as offer from t
union all select customer_id, offer_2 from t
union all select customer_id, offer_3 from t
) x
group by customer_id
) y
结果:
DISTINCT_OFFERS
---------------
2
参见 db<>fiddle 中的 运行 示例。
没有UNION ALL的解决方案。它应该有更好的性能。
/*
WITH MYTAB (Customer_ID, Offer_1, Offer_2, Offer_3) AS
(
VALUES
(111, 'A01', '001', 'B01')
, (222, 'A01', 'B01', '001')
, (333, 'A02', '001', 'B01')
)
*/
SELECT COUNT (DISTINCT LIST)
FROM
(
SELECT LISTAGG (V.Offer, '|') WITHIN GROUP (ORDER BY V.Offer) LIST
FROM MYTAB T
CROSS JOIN TABLE (VALUES T.Offer_1, T.Offer_2, T.Offer_3) V (Offer)
GROUP BY T.CUSTOMER_ID
)