根据几个条件加入两个 table,这会导致两个 table 的一些 TOP 数据
Joining two table based on few conditions which results in some TOP data from two tables
我正在尝试通过连接两个 SQL table 和 return 第二个 table 的最新值和所有来自第一个 table 的行类似于左连接以及来自 table2 的 TOP 1 记录,其中 table1 中没有匹配项,按产品、等级、术语
分组
我的问题可以用下面的例子清楚地解释。
Table1
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
Table2
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
和 Table2
,只要 table 的列 Product,Grade and Term
相等且 return来自 Table1
的所有行,同时将来自 Table2
的列 TradeValue
的最新值连接到匹配的第一条记录,并为结果视图的其他行制作 TradeValue as NULL
和结果视图应该有 Table2
的 Id
作为 LTID
并且它也应该 return 来自 Table 2 的 TOP 1 行,其中 Product、Grade 和 Term 不是按产品、等级和期限进行平等分组
所以结果 SQL 视图应该是
结果
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
中的所有匹配行,而且我无法 return 来自 [=67= 的 TOP 1 行]2 未找到匹配项
我可以知道更好的处理方法吗?
试试这个:
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
由于您使用的是 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
我正在尝试通过连接两个 SQL table 和 return 第二个 table 的最新值和所有来自第一个 table 的行类似于左连接以及来自 table2 的 TOP 1 记录,其中 table1 中没有匹配项,按产品、等级、术语
分组我的问题可以用下面的例子清楚地解释。
Table1
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
Table2
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
和 Table2
,只要 table 的列 Product,Grade and Term
相等且 return来自 Table1
的所有行,同时将来自 Table2
的列 TradeValue
的最新值连接到匹配的第一条记录,并为结果视图的其他行制作 TradeValue as NULL
和结果视图应该有 Table2
的 Id
作为 LTID
并且它也应该 return 来自 Table 2 的 TOP 1 行,其中 Product、Grade 和 Term 不是按产品、等级和期限进行平等分组
所以结果 SQL 视图应该是
结果
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
中的所有匹配行,而且我无法 return 来自 [=67= 的 TOP 1 行]2 未找到匹配项
我可以知道更好的处理方法吗?
试试这个:
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
由于您使用的是 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