在 SQL 服务器查询中的加入操作期间避免重复
Avoid duplicates during the Join operation in SQL Server Query
我有几个如下所示的日期表
Date1(存储每个型号的折扣日期)
Year Model DiscountDate
2018 99L263 1/1/2017
2018 99L263 1/8/2018
2018 99L263 5/24/2018
Date2(存储每个型号的价格日期)
Year Model PriceDate
2018 99L263 1/1/2017
2018 99L263 1/8/2018
2018 99L263 3/1/2018
我正在尝试查找每个型号的所有折扣和价格日期。它导致笛卡尔积。
SELECT D1.Year
,D1.Model
,D1.DiscountDate
,D2.PriceDate
FROM Date1 D1
INNER JOIN Date2 D2 ON D1.Year = D2.Year
AND D1.Model = D2.Model
我得到这样的输出
Year Model DiscountDate PriceDate
2018 99L263 1/1/2017 1/1/2017
2018 99L263 1/1/2017 1/8/2018
2018 99L263 1/1/2017 3/1/2018
2018 99L263 1/8/2018 1/1/2017
2018 99L263 1/8/2018 1/8/2018
2018 99L263 1/8/2018 3/1/2018
2018 99L263 5/24/2018 1/1/2017
2018 99L263 5/24/2018 1/8/2018
2018 99L263 5/24/2018 3/1/2018
我的预期输出是
Year Model DiscountDate PriceDate
2018 99L263 1/1/2017 1/1/2017
2018 99L263 1/8/2018 1/8/2018
2018 99L263 5/24/2018 3/1/2018
我没有在加入条件中包含折扣日期,因为我无法加入日期,因为它可能彼此匹配也可能不匹配。
您的结果并不是真正的关系格式 table。这些列彼此之间没有任何关系。但是,您可以使用 row_number()
和条件聚合来做您想做的事:
select year, model,
max(discountdate) as discountdate,
max(pricedate) as pricedate
from ((select year, model, discountdate, null as pricedate
row_number() over (partition by year, model order by pricedate) as seqnum
from discounts
) union all
(select year, model, null, pricedate,
row_number() over (partition by year, model order by pricedate) as seqnum
from prices
)
) pd
group by year, model, seqnum;
with cte1 as
(Select *, Row_Number() over (partition by year, model order by DiscountDate) as ranking from date1)
, cte2 as
(Select *, Row_Number() over (partition by year, model order by pricedate) as ranking from date2)
SELECT D1.Year
,D1.Model
,D1.DiscountDate
,D2.PriceDate
FROM cte1 D1
INNER JOIN cte2 D2 ON D1.Year = D2.Year
AND D1.Model = D2.Model AND D1.ranking = D2.ranking
如果 pricedate 是日期数据类型,那么您可以使用子查询而不是联接来获得所需的输出。下面的示例应该 return 所需的输出。
SELECT D1.Year
,D1.Model
,D1.DiscountDate
,(SELECT MAX(D2.PriceDate)
FROM Date2 D2
WHERE D2.Model = D1.Model
AND D2.Year = D1.Year
AND D2.PriceDate <= D1.DiscountDate
) AS PriceDate
FROM Date1 D1
我有几个如下所示的日期表
Date1(存储每个型号的折扣日期)
Year Model DiscountDate
2018 99L263 1/1/2017
2018 99L263 1/8/2018
2018 99L263 5/24/2018
Date2(存储每个型号的价格日期)
Year Model PriceDate
2018 99L263 1/1/2017
2018 99L263 1/8/2018
2018 99L263 3/1/2018
我正在尝试查找每个型号的所有折扣和价格日期。它导致笛卡尔积。
SELECT D1.Year
,D1.Model
,D1.DiscountDate
,D2.PriceDate
FROM Date1 D1
INNER JOIN Date2 D2 ON D1.Year = D2.Year
AND D1.Model = D2.Model
我得到这样的输出
Year Model DiscountDate PriceDate
2018 99L263 1/1/2017 1/1/2017
2018 99L263 1/1/2017 1/8/2018
2018 99L263 1/1/2017 3/1/2018
2018 99L263 1/8/2018 1/1/2017
2018 99L263 1/8/2018 1/8/2018
2018 99L263 1/8/2018 3/1/2018
2018 99L263 5/24/2018 1/1/2017
2018 99L263 5/24/2018 1/8/2018
2018 99L263 5/24/2018 3/1/2018
我的预期输出是
Year Model DiscountDate PriceDate
2018 99L263 1/1/2017 1/1/2017
2018 99L263 1/8/2018 1/8/2018
2018 99L263 5/24/2018 3/1/2018
我没有在加入条件中包含折扣日期,因为我无法加入日期,因为它可能彼此匹配也可能不匹配。
您的结果并不是真正的关系格式 table。这些列彼此之间没有任何关系。但是,您可以使用 row_number()
和条件聚合来做您想做的事:
select year, model,
max(discountdate) as discountdate,
max(pricedate) as pricedate
from ((select year, model, discountdate, null as pricedate
row_number() over (partition by year, model order by pricedate) as seqnum
from discounts
) union all
(select year, model, null, pricedate,
row_number() over (partition by year, model order by pricedate) as seqnum
from prices
)
) pd
group by year, model, seqnum;
with cte1 as
(Select *, Row_Number() over (partition by year, model order by DiscountDate) as ranking from date1)
, cte2 as
(Select *, Row_Number() over (partition by year, model order by pricedate) as ranking from date2)
SELECT D1.Year
,D1.Model
,D1.DiscountDate
,D2.PriceDate
FROM cte1 D1
INNER JOIN cte2 D2 ON D1.Year = D2.Year
AND D1.Model = D2.Model AND D1.ranking = D2.ranking
如果 pricedate 是日期数据类型,那么您可以使用子查询而不是联接来获得所需的输出。下面的示例应该 return 所需的输出。
SELECT D1.Year
,D1.Model
,D1.DiscountDate
,(SELECT MAX(D2.PriceDate)
FROM Date2 D2
WHERE D2.Model = D1.Model
AND D2.Year = D1.Year
AND D2.PriceDate <= D1.DiscountDate
) AS PriceDate
FROM Date1 D1