基于少数列的相等性加入两个SQL表

时间:2015-01-26 20:11:08

标签: sql-server join sql-server-2012

我试图通过连接两个SQL表来创建一个SQL视图,并且只返回第二个表中的最低值和第一个表中与左连接类似的所有行。

我的问题可以通过下面的例子清楚地解释。

表1

Id  Product Grade Term Bid Offer 
100 ABC       A   Q1   10  20
101 ABC       A   Q1   5   25
102 XYZ       A   Q2   25  30
103 XYZ       B   Q2   20  30

表2

Id Product Grade Term TradeValue
1  ABC     A     Q1     100
2  ABC     A     Q1     95    
3  XYZ     B     Q2     100

在上面的数据中,我希望在两个表中的Table1列相等时加入Table2Product,Grade and Term,并在加入时返回Table1的所有行从TradeValue到匹配的第一条记录的Table2列的最低值,并为结果视图的其他行创建TradeValue as NULL,生成的视图应该包含Id Table2作为LTID

因此生成的SQL视图应为

RESULT

   Id  Product Grade Term Bid Offer TradeValue LTID
   100  ABC       A   Q1   10   20     95         2
   101  ABC       A   Q1   5    25    NULL        2
   102  XYZ       A   Q2   25   30    NULL       NULL
   103  XYZ       B   Q2   20   30    100         3

我尝试使用以下查询

CREATE VIEW [dbo].[ViewCC]
AS
SELECT
a.Id,a.Product,a.Grade,a.Term,a.Bid,a.Offer,
b.TradeValue
FROM Table1 AS a 
left  JOIN (SELECT Product,Grade,Term,MIN(TradeValue) TradeValue from  Table2 Group by Product,Grade,Term,) AS b
 ON  b.Product=a.Product
and b.Grade=a.Grade
and b.Term=a.Term 
GO

上面的Query返回了以下数据,这些数据很容易出现在我写的查询中,但这不是我想要获取的数据

 Id  Product Grade Term Bid Offer TradeValue 
 100   ABC      A   Q1   10   20      95       
 101   ABC      A   Q1   5    25      95 --This should be null     
 102   XYZ      A   Q2   25   30     NULL     
 103   XYZ      B   Q2   20   30     100      

我们可以看到TradeValue的最小值被分配给Table1中的所有匹配行,而且我无法从Table2返回Id As LTID,因为我遇到{{1}的问题我不能用 b.Id 对它进行分组,因为它会返回太多行。

我可以知道更好的解决方法吗?

1 个答案:

答案 0 :(得分:1)

您需要在Table1的每条记录附加一个行号,这样才能满足只加入Table1每组的第一条记录的要求:

CREATE VIEW [dbo].[ViewCC]
AS
SELECT a.Id, a.Product, a.Grade, a.Term, a.Bid, a.Offer, 
       b.TradeValue, b.Id AS LTID
FROM (
  SELECT *, ROW_NUMBER() OVER(PARTITION BY Product, Grade, Term ORDER BY Id) AS rn
  FROM Table1
) a
OUTER APPLY (
  SELECT TOP 1 CASE WHEN rn = 1 THEN TradeValue
                    ELSE NULL
               END AS TradeValue, Id 
  FROM  Table2
  WHERE Product=a.Product AND Grade=a.Grade AND Term=a.Term
  ORDER BY TradeValue) b  
GO

OUTER APPLY返回一个表格表达式,其中包含Table2TradeValue最低的匹配记录,如果不存在匹配记录,则为NULL