実際のテーブル定義やサンプル データがなければ、扱いにくいものです。だから私はいくつかを作りました:
create table Carts(
id int,
customerid int,
productid int
)
create table Groups(
groupid int,
groupname int,
discountamount int
)
create table GroupProducts(
groupproductid int,
groupid int,
productid int
)
insert into Carts (id,customerid,productid) values
(1,1,1),
(2,1,2),
(3,1,4),
(4,2,2),
(5,2,3)
insert into Groups (groupid,groupname,discountamount) values
(1,1,10),
(2,2,15),
(3,3,20)
insert into GroupProducts (groupproductid,groupid,productid) values
(1,1,1),
(2,1,5),
(3,2,2),
(4,2,4),
(5,3,2),
(6,3,3)
;With MatchedProducts as (
select
c.customerid,gp.groupid,COUNT(*) as Cnt
from
Carts c
inner join
GroupProducts gp
on
c.productid = gp.productid
group by
c.customerid,gp.groupid
), GroupSizes as (
select groupid,COUNT(*) as Cnt from GroupProducts group by groupid
), MatchingGroups as (
select
mp.*
from
MatchedProducts mp
inner join
GroupSizes gs
on
mp.groupid = gs.groupid and
mp.Cnt = gs.Cnt
)
select * from MatchingGroups
これにより、次の結果が生成されます。
customerid groupid Cnt
----------- ----------- -----------
1 2 2
2 3 2
ここで行っているのは「関係分割」と呼ばれるものです。この用語を他の場所で検索したい場合に使用します。私の現在の結果では、各顧客は 1 つのグループにのみ一致します。複数の一致がある場合は、報告するグループを決定するためにタイブレーク条件が必要です。コメントで 2 つの提案 (最低groupid
または最高discountamount
) を求めました。「以前に追加された」という回答は役に立ちません。グループの追加日を含む列がありません。行には、SQL 固有の順序はありません。
MatchingGroups
の定義と最終選択でタイブレークを行います。
MatchingGroups as (
select
mp.*,
ROW_NUMBER() OVER (PARTITION BY mp.customerid ORDER BY /*Tie break criteria here */) as rn
from
MatchedProducts mp
inner join
GroupSizes gs
on
mp.groupid = gs.groupid and
mp.Cnt = gs.Cnt
)
select * from MatchingGroups where rn = 1