2012-11-23 84 views
3

我有2個簡單的表,我想執行一個INNER JOIN用,但問題是,我就要複製(用於列str1和str2的)結果:重複的結果時,INNER JOIN

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 

它給了我4個記錄時,我真的很想2.

我得到了什麼:
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

我真正想要的東西:
1 | b | 7 | a | b
2 a | b | 8 | a | b

誰能幫助?我知道這是可以實現的使用遊標和循環,但我想避免它,只使用某種類型的JOIN,如果可能的話。

回答

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退還加盟任LEFTRIGHTFULL加入。

+0

謝謝,這個作品很棒! – codetc

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記錄結合起來。

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; 

這對加入其ID排序位置A和B之間的項目。但請注意:如果您對每組Str1和Str2有不同數量的項目,您可能會收到意外的結果,因爲#A或#B會顯示NULL。

我在這裏假設您要按照#A.Id(1爲第一個)的順序排列第一行表#A的「Str1 Str2」,以便與表#B的第一行「Str1 Str2 「,按照#B.Id(7是第一個)的順序,等等等等等等。是對的嗎?

但你會怎麼做,如果行數不匹配,並且有,例如,3行中#A有在#B 2行相同的值?或者相反?你要看什麼?

區區不同,因爲數據不重複也​​不會做的工作。你得到的是部分交叉連接(導致部分笛卡爾乘積)。也就是說,您的加入標準不能確保#A行到#B行之間存在一對一的對應關係。當發生這種情況,對於每個在#A,你會得到每個匹配的行輸出行B. 2×2 = 4,而不是2。

我認爲這會有所幫助,如果你是在你的例子中更具體一點。你究竟在詢問什麼?當然你已經爲我們簡化了,但是這也消除了所有情況,讓我們知道你在現實世界中想要完成什麼。如果您嘗試排隊參加運動隊,我們可能會給出不同的答案,如果您嘗試排列發票行項目或遲到事件或誰知道什麼!

+0

感謝ErikE,這也按預期工作,只要我在每個表中有相同的記錄數。我的情況很複雜,這就是爲什麼我簡化它。基本上我的目標是獲得一對一的匹配結果,我將需要使用它來進一步計算。 – codetc