我有2个简单的表格,我想用INNER JOIN执行,但问题是我得到重复(对于列str1和str2)结果:
CREATE TABLE #A (Id INT, str1 nvarchar(50), str2 nvarchar(50))
insert into #A values (1, 'a', 'b')
insert into #A values (2, 'a', 'b')
CREATE TABLE #B (Id INT, str1 nvarchar(50), str2 nvarchar(50))
insert into #B values (7, 'a', 'b')
insert into #B values (8, 'a', 'b')
select * from #A a
INNER JOIN #B b ON a.str1 = b.str1 AND a.str2 = b.str2
当我真正想要2时,它给了我4条记录。
我得到了什么:
id | str1 | STR2 | id | str1 | STR2
1 | a | b | 7 | a | b
2 | a | b | 7 | a | b
1 | a | b | 8 | a | b
2 | a | b | 8 | a | B'/ P>
我真正想要的是什么:
1 a | b | 7 | a | b
2 a | b | 8 | a | B'/ P>
有人可以帮忙吗?我知道这是可以使用游标和循环实现的,但是我想避免它,并且如果可能的话只使用某种类型的JOIN。
答案 0 :(得分:5)
SELECT
a.id AS a_id, a.str1 AS a_str1, a.str2 AS a_str2,
b.id AS b_id, b.str1 AS b_str1, b.str2 AS b_str2
FROM
( SELECT *
, ROW_NUMBER() OVER (PARTITION BY str1, str2 ORDER BY id) AS rn
FROM #A
) a
INNER JOIN
( SELECT *
, ROW_NUMBER() OVER (PARTITION BY str1, str2 ORDER BY id) AS rn
FROM #B
) b
ON a.str1 = b.str1
AND a.str2 = b.str2
AND a.rn = b.rn ;
如果同一(str1, str2)
组合的一个或另一个表中有更多行,您可以通过将INNER
联接更改为LEFT
,{{{}来选择要返回的行1}}或RIGHT
加入。
答案 1 :(得分:3)
您可以完成与以下查询的匹配(SQL 2005及更高版本):
WITH A AS (
SELECT
Seq = Row_Number() OVER (PARTITION BY Str1, Str2 ORDER BY Id),
*
FROM #A
), B AS (
SELECT
Seq = Row_Number() OVER (PARTITION BY Str1, Str2 ORDER BY Id),
*
FROM #B
)
SELECT
A.Id, A.Str1, A.Str2, B.Id, B.Str1, B.Str2
FROM
A
FULL JOIN B
ON A.Seq = B.Seq AND A.Str1 = B.Str1 AND A.Str2 = B.Str2;
这会将A和B之间的项目连接到其ID顺序位置。但请注意:如果每组Str1和Str2的项目数不等,则可能会出现意外结果,因为#A或#B会出现NULL。
我假设你想要第一行表#A的“Str1 Str2”,按#A.Id(1为第一个)排序,与表#B的第一行“Str1 Str2”相关联,按照#B.Id(7为第一个)的顺序排序,依此类推,每个连续编号的行。是吗?
但是如果行数不匹配,你会怎么做?例如,#A中有3行与#B中的2行具有相同的值?或者相反?你想看到什么?
仅仅是DISTINCT不能完成这项工作,因为数据不会重复。您将获得实际上是部分交叉连接(导致部分笛卡尔积)。也就是说,您的连接标准不能确保#A行与#B行一一对应。当发生这种情况时,对于#A中的每个行,您将获得 B中每个匹配行的输出行.2 x 2 = 4,而不是2。
我认为如果你在你的例子中更具体一点,那会有所帮助。你实际在查询什么?当然,你已经为我们简化了,但这也消除了我们知道你在现实世界中想要完成什么的所有背景。如果你试图排队运动队,我们可能会提供一个不同的答案,而不是你试图排队发票行项目或迟到的事件或谁知道什么!
答案 2 :(得分:1)
使用这些数据,只有那些数据,你无法得到你想要的结果,除非你能够为每个#A的ID值提供一些方法来映射到每个#B的ID值。
所以,如果你真的在每个表中只有2条记录,它会是这样的:
SELECT *
FROM #A a
JOIN #B b
ON a.str1 = b.str1 -- actually, if you join by IDs this isn't necessary
AND a.str2 = b.str2 -- nor is this
AND
(
( a.ID = 1 and b.ID = 7 )
OR ( a.ID = 2 and b.ID = 8 )
)
您获得的内容称为笛卡尔积,其中#A中的每条记录与#B中的每条匹配记录配对。由于每个表中有多个匹配记录,因此您可以获得A和B中匹配记录的所有可能组合。
由于您必须使用的其他唯一字段是ID字段,因此您需要使用这些字段将一个A记录与一个B记录完全组合。