基于几个条件连接两个表,这两个表导致来自两个表的一些TOP数据

时间:2015-01-29 14:26:12

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

我试图通过连接两个SQL表来创建一个SQL视图并返回第二个表中的最新值,并且第一个表中的所有行类似于左连接以及来自table2的TOP 1记录,其中表中没有匹配1按产品,等级,术语分组

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

表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
4  PQR     C     Q2     100
5  PQR     C     Q2     200

在上面的数据中,我希望在两个表中的Table1列相等时加入Table2Product,Grade and Term,并在加入时返回Table1的所有行从TradeValue到匹配的第一条记录的Table2列的最新值,并为结果视图的其他行创建TradeValue as NULL,生成的视图应该包含Id Table2作为LTID并且它还应返回表2中的前1行,其中产品,等级和期限不等于按产品,等级和期限分组

因此生成的SQL视图应为

RESULT

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

我尝试使用以下查询

http://sqlfiddle.com/#!3/e8884/7

我们可以看到TradeValue的最新值被分配给Table1中的所有匹配行,而且我也无法返回Table2中未找到匹配项的TOP 1行

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

2 个答案:

答案 0 :(得分:1)

试试这个:

SELECT ROW_NUMBER() OVER(ORDER BY d.Product) as ID,d.*,t1.Bid,t1.Offer,t2.LastTradeValue,t2.ID AS LTID 
FROM
(
  SELECT Product,Grade,Term
  FROM Table1
  UNION 
  SELECT Product,Grade,Term
  FROM Table2 
) d
LEFT JOIN Table1 t1 ON d.Product=t1.Product AND d.Grade=t1.Grade AND d.Term=t1.Term
OUTER APPLY 
(
  SELECT TOP 1 * FROM Table2 t2 WHERE d.Product=t2.Product AND d.Grade=t2.Grade AND d.Term=t2.Term
  ORDER BY t2.ID DESC
) t2

答案 1 :(得分:0)

由于您使用的是Sql Server 2012,请让我建议以下内容:

DECLARE @t1 TABLE
    (
      Id INT ,
      Product CHAR(3) ,
      Grade CHAR(1) ,
      Term CHAR(2) ,
      Bid INT ,
      Offer INT
    )
DECLARE @t2 TABLE
    (
      Id INT ,
      Product CHAR(3) ,
      Grade CHAR(1) ,
      Term CHAR(2) ,
      TradeValue INT
    )

INSERT  INTO @t1
VALUES  ( 100, 'ABC', 'A', 'Q1', 10, 20 ),
        ( 101, 'ABC', 'A', 'Q1', 5, 25 ),
        ( 102, 'XYZ', 'A', 'Q2', 25, 30 ),
        ( 103, 'XYZ', 'B', 'Q2', 20, 30 )

INSERT  INTO @t2
VALUES  ( 1, 'ABC', 'A', 'Q1', 100 ),
        ( 2, 'ABC', 'A', 'Q1', 95 ),
        ( 3, 'XYZ', 'B', 'Q2', 100 ),
        ( 4, 'PQR', 'C', 'Q2', 100 ),
        ( 5, 'PQR', 'C', 'Q2', 200 ),
        ( 6, 'TTT', 'C', 'Q2', 200 ),
        ( 7, 'TTT', 'C', 'Q2', 201 ),
        ( 8, 'JJJ', 'C', 'Q2', 500 );

WITH    cte
          AS ( SELECT   t1.Id AS t1Id ,
                        t1.Product AS t1Product ,
                        t1.Grade AS t1Grade ,
                        t1.Term AS t1Term ,
                        t1.Bid AS t1Bid ,
                        t1.Offer AS t1Offer ,
                        IIF(t1.ID IS NULL, t1.Id, t2.Id) AS ordert2Id ,
                        t2.Id AS t2Id ,
                        t2.Product AS t2Product ,
                        t2.Grade AS t2Grade ,
                        t2.Term AS t2Term ,
                        t2.TradeValue AS t2TradeValue
               FROM     @t2 t2
                        FULL JOIN @t1 t1 ON t2.Product = t1.Product
                                            AND t2.Grade = t1.Grade
                                            AND t2.Term = t1.Term
             ),
        cte2
          AS ( SELECT   * ,
                        ROW_NUMBER() OVER ( PARTITION BY t2Product, t2Grade, t2Term, t1Id ORDER BY ordert2Id ) AS rn1 ,
                        RANK() OVER ( PARTITION BY t2Product, t2Grade, t2Term ORDER BY t1Id ) AS rn2 ,
                        LAST_VALUE(t2TradeValue) OVER ( PARTITION BY t2Product, t2Grade, t2Term ORDER BY ordert2Id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS TradeValue ,
                        LAST_VALUE(t2Id) OVER ( PARTITION BY t2Product, t2Grade, t2Term ORDER BY t2Id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS TradeId
               FROM     cte
             )
    SELECT  t1Id AS ID ,
            ISNULL(t1Product, t2Product) AS Product ,
            ISNULL(t1Grade, t2Grade) AS Product ,
            ISNULL(t1Term, t2Term) AS Product ,
            t1Bid AS Bid ,
            t1Offer AS Offer,
            IIF(rn2 = 1, TradeValue, NULL) AS TradeValue,
            IIF(rn2 = 1, TradeId, NULL) AS LTID

    FROM    cte2
    WHERE   rn1 = 1

输出:

ID   Product    Product Product Bid  Offer  TradeValue  LTID
NULL PQR        C       Q2      NULL NULL   200         5
100  ABC        A       Q1      10   20     95          2
101  ABC        A       Q1      5    25     NULL        NULL
102  XYZ        A       Q2      25   30     NULL        NULL
103  XYZ        B       Q2      20   30     100         3
相关问题