在 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