Return 结果基于两个基于 Id 的结果集,不考虑行数
Return result based on two results set based on Id, irrespective of rows count
我从两个不同的来源 @Table1, @Table2
接收数据集,table 都有 Id
列。对于相同的 ID,两个来源 return 不同数量的记录。
我想合并基于 @MainTable
的结果,它具有来自 @Table1
和 @Table2
的所有可能 ID。如果另一个 table 没有相同数量的记录,那么它可以与 NULL
.
一起应用
示例数据和table设计:
DECLARE @MainTable TABLE (Id INT, [Name] VARCHAR (50));
INSERT INTO @MainTable (Id, [Name]) VALUES (1, 'One'), (2, 'Two'), (3, 'Three');
DECLARE @Table1 TABLE (Id INT, Val1 INT, Val2 INT);
INSERT INTO @Table1 (Id, Val1, Val2) VALUES
(1, 11, 12), (1, 22, 23), (1, 33, 34), (1, 38, 39),
(2, 31, 32), (2, 34, 35),
(3, 44, 45);
DECLARE @Table2 TABLE (Id INT, Val3 INT, Val4 INT);
INSERT INTO @Table2 (Id, Val3, Val4) VALUES
(1, 20, 21), (1, 25, 26),
(2, 30, 31), (2, 33, 34), (2, 36, 37), (2, 38, 39), (2, 40, 41),
(3, 51, 52), (3, 54, 55), (3, 56, 57), (3, 58, 59);
预期输出:
Id
Name
Val1
Val2
Val3
Val4
1
One
11
12
20
21
1
One
22
23
25
26
1
One
33
34
NULL
NULL
1
One
38
39
NULL
NULL
2
Two
31
32
30
31
2
Two
34
35
33
34
2
Two
NULL
NULL
36
37
2
Two
NULL
NULL
38
39
2
Two
NULL
NULL
40
41
3
Three
44
55
51
52
3
Three
NULL
NULL
54
55
3
Three
NULL
NULL
56
57
3
Three
NULL
NULL
58
59
我正在使用 SQL Server 2012。我已经尝试了下面的一些代码,但没有帮助:
SELECT MT.Id, MT.[Name], A.Val1, A.Val2, B.Val3, B.Val4
FROM @MainTable MT
OUTER APPLY ( SELECT * FROM @Table1 T1 WHERE T1.Id = MT.Id ) A
OUTER APPLY ( SELECT * FROM @Table2 T2 WHERE T2.Id = MT.Id ) B
SELECT *
FROM @MainTable MT
LEFT OUTER JOIN @Table1 T1 ON T1.Id = MT.Id
LEFT OUTER JOIN @Table2 T2 ON T2.Id = MT.Id
在行之间读取,但如果您不关心哪些行连接到哪些行(因为我看不到 @Table1
到 @Table2
中的行之间没有关系),您可以这样做:
WITH T1 AS(
SELECT T1.Id,
T1.Val1,
T1.Val2,
ROW_NUMBER() OVER (PARTITION BY T1.Id ORDER BY (SELECT NULL)) AS RN --Define your ORDER BY properly here
FROM @Table1 T1),
T2 AS(
SELECT T2.Id,
T2.Val3,
T2.Val4,
ROW_NUMBER() OVER (PARTITION BY T2.Id ORDER BY (SELECT NULL)) AS RN --Define your ORDER BY properly here
FROM @Table2 T2),
RNs AS(
SELECT T1.Id,
T1.RN
FROM T1
UNION
SELECT T2.Id,
T2.RN
FROM T2)
SELECT MT.Id,
T1.Val1,
T1.Val2,
T2.Val3,
T2.Val4
FROM @MainTable MT
JOIN RNs ON MT.Id = RNs.Id
LEFT JOIN T1 ON RNs.Id = T1.ID
AND RNs.RN = T1.RN
LEFT JOIN T2 ON RNs.Id = T2.ID
AND RNs.RN = T2.RN;
Larnu 先于我。但我仍在发布我的答案,因为我认为如果数据集变大,我的答案会更快一些。
DECLARE @MainTable TABLE (Id INT, [Name] VARCHAR (50));
INSERT INTO @MainTable (Id, [Name]) VALUES (1, 'One'), (2, 'Two'), (3, 'Three');
DECLARE @Table1 TABLE (Id INT, Val1 INT, Val2 INT);
INSERT INTO @Table1 (Id, Val1, Val2) VALUES
(1, 11, 12), (1, 22, 23), (1, 33, 34), (1, 38, 39),
(2, 31, 32), (2, 34, 35),
(3, 44, 45);
DECLARE @Table2 TABLE (Id INT, Val3 INT, Val4 INT);
INSERT INTO @Table2 (Id, Val3, Val4) VALUES
(1, 20, 21), (1, 25, 26),
(2, 30, 31), (2, 33, 34), (2, 36, 37), (2, 38, 39), (2, 40, 41),
(3, 51, 52), (3, 54, 55), (3, 56, 57), (3, 58, 59);
with cte1 as (
select
t1.*,
row_number() over (partition by t1.Id order by t1.Val1) as seqno
from @Table1 t1
),
cte2 as (
select
t2.*,
row_number() over (partition by t2.Id order by t2.Val3) as seqno
from @Table2 t2
),
cte3 as (
select isnull(c1.Id, c2.Id) as Id, c1.Val1, c1.Val2, c2.Val3, c2.Val4
from cte1 c1
full outer join cte2 c2 on (c2.Id = c1.Id and c2.seqno = c1.seqno)
)
select
m.Id,
m.[Name],
c3.Val1,
c3.Val2,
c3.Val3,
c3.Val4
from @MainTable m
left outer join cte3 c3 on (c3.Id = m.Id);
我从两个不同的来源 @Table1, @Table2
接收数据集,table 都有 Id
列。对于相同的 ID,两个来源 return 不同数量的记录。
我想合并基于 @MainTable
的结果,它具有来自 @Table1
和 @Table2
的所有可能 ID。如果另一个 table 没有相同数量的记录,那么它可以与 NULL
.
示例数据和table设计:
DECLARE @MainTable TABLE (Id INT, [Name] VARCHAR (50));
INSERT INTO @MainTable (Id, [Name]) VALUES (1, 'One'), (2, 'Two'), (3, 'Three');
DECLARE @Table1 TABLE (Id INT, Val1 INT, Val2 INT);
INSERT INTO @Table1 (Id, Val1, Val2) VALUES
(1, 11, 12), (1, 22, 23), (1, 33, 34), (1, 38, 39),
(2, 31, 32), (2, 34, 35),
(3, 44, 45);
DECLARE @Table2 TABLE (Id INT, Val3 INT, Val4 INT);
INSERT INTO @Table2 (Id, Val3, Val4) VALUES
(1, 20, 21), (1, 25, 26),
(2, 30, 31), (2, 33, 34), (2, 36, 37), (2, 38, 39), (2, 40, 41),
(3, 51, 52), (3, 54, 55), (3, 56, 57), (3, 58, 59);
预期输出:
Id | Name | Val1 | Val2 | Val3 | Val4 |
---|---|---|---|---|---|
1 | One | 11 | 12 | 20 | 21 |
1 | One | 22 | 23 | 25 | 26 |
1 | One | 33 | 34 | NULL | NULL |
1 | One | 38 | 39 | NULL | NULL |
2 | Two | 31 | 32 | 30 | 31 |
2 | Two | 34 | 35 | 33 | 34 |
2 | Two | NULL | NULL | 36 | 37 |
2 | Two | NULL | NULL | 38 | 39 |
2 | Two | NULL | NULL | 40 | 41 |
3 | Three | 44 | 55 | 51 | 52 |
3 | Three | NULL | NULL | 54 | 55 |
3 | Three | NULL | NULL | 56 | 57 |
3 | Three | NULL | NULL | 58 | 59 |
我正在使用 SQL Server 2012。我已经尝试了下面的一些代码,但没有帮助:
SELECT MT.Id, MT.[Name], A.Val1, A.Val2, B.Val3, B.Val4
FROM @MainTable MT
OUTER APPLY ( SELECT * FROM @Table1 T1 WHERE T1.Id = MT.Id ) A
OUTER APPLY ( SELECT * FROM @Table2 T2 WHERE T2.Id = MT.Id ) B
SELECT *
FROM @MainTable MT
LEFT OUTER JOIN @Table1 T1 ON T1.Id = MT.Id
LEFT OUTER JOIN @Table2 T2 ON T2.Id = MT.Id
在行之间读取,但如果您不关心哪些行连接到哪些行(因为我看不到 @Table1
到 @Table2
中的行之间没有关系),您可以这样做:
WITH T1 AS(
SELECT T1.Id,
T1.Val1,
T1.Val2,
ROW_NUMBER() OVER (PARTITION BY T1.Id ORDER BY (SELECT NULL)) AS RN --Define your ORDER BY properly here
FROM @Table1 T1),
T2 AS(
SELECT T2.Id,
T2.Val3,
T2.Val4,
ROW_NUMBER() OVER (PARTITION BY T2.Id ORDER BY (SELECT NULL)) AS RN --Define your ORDER BY properly here
FROM @Table2 T2),
RNs AS(
SELECT T1.Id,
T1.RN
FROM T1
UNION
SELECT T2.Id,
T2.RN
FROM T2)
SELECT MT.Id,
T1.Val1,
T1.Val2,
T2.Val3,
T2.Val4
FROM @MainTable MT
JOIN RNs ON MT.Id = RNs.Id
LEFT JOIN T1 ON RNs.Id = T1.ID
AND RNs.RN = T1.RN
LEFT JOIN T2 ON RNs.Id = T2.ID
AND RNs.RN = T2.RN;
Larnu 先于我。但我仍在发布我的答案,因为我认为如果数据集变大,我的答案会更快一些。
DECLARE @MainTable TABLE (Id INT, [Name] VARCHAR (50));
INSERT INTO @MainTable (Id, [Name]) VALUES (1, 'One'), (2, 'Two'), (3, 'Three');
DECLARE @Table1 TABLE (Id INT, Val1 INT, Val2 INT);
INSERT INTO @Table1 (Id, Val1, Val2) VALUES
(1, 11, 12), (1, 22, 23), (1, 33, 34), (1, 38, 39),
(2, 31, 32), (2, 34, 35),
(3, 44, 45);
DECLARE @Table2 TABLE (Id INT, Val3 INT, Val4 INT);
INSERT INTO @Table2 (Id, Val3, Val4) VALUES
(1, 20, 21), (1, 25, 26),
(2, 30, 31), (2, 33, 34), (2, 36, 37), (2, 38, 39), (2, 40, 41),
(3, 51, 52), (3, 54, 55), (3, 56, 57), (3, 58, 59);
with cte1 as (
select
t1.*,
row_number() over (partition by t1.Id order by t1.Val1) as seqno
from @Table1 t1
),
cte2 as (
select
t2.*,
row_number() over (partition by t2.Id order by t2.Val3) as seqno
from @Table2 t2
),
cte3 as (
select isnull(c1.Id, c2.Id) as Id, c1.Val1, c1.Val2, c2.Val3, c2.Val4
from cte1 c1
full outer join cte2 c2 on (c2.Id = c1.Id and c2.seqno = c1.seqno)
)
select
m.Id,
m.[Name],
c3.Val1,
c3.Val2,
c3.Val3,
c3.Val4
from @MainTable m
left outer join cte3 c3 on (c3.Id = m.Id);