2017-06-28 73 views
1

我無法理解如何在不創建重複記錄的情況下將三個表連接在一起。如何正確加入和分組

我有一個使用表的個人資料我的第一個查詢,多部未華儀器:

SELECT 
    [p].[shopper_id] 
, [pi].[instrument_id] 
FROM 
    [dbo].[profile] [p] 
INNER JOIN [dbo].[profile_instruments] [pi] 
ON [pi].[PID] = [p].[PID] 
WHERE 
    [p].[date_created] > DATEADD(yy, -2, GETDATE()) 
    AND [p].[shopper_id] = '53D5444535434747A935E207C9EDD96A' 
ORDER BY 
    [p].[shopper_id]; 

該查詢給我的結果:

shopper_id instrument_id 
53D5444535434747A935E207C9EDD96A 35 
53D5444535434747A935E207C9EDD96A 17 

我的第二個查詢使用表的個人資料和表格樣式:

SELECT 
    [p].[shopper_id] 
, [ps].[style_id] 
FROM 
    [dbo].[profile] [p] 
INNER JOIN [dbo].[profile_styles] [ps] 
ON [ps].[PID] = [p].[PID] 
WHERE 
    [p].[date_created] > DATEADD(yy, -2, GETDATE()) 
    AND [p].[shopper_id] = '53D5444535434747A935E207C9EDD96A' 
ORDER BY 
    [p].[shopper_id]; 

結果是:

shopper_id style_id 
53D5444535434747A935E207C9EDD96A 845 
53D5444535434747A935E207C9EDD96A 291 

當我結合了3代表的個人資料,儀器儀表和風格:

SELECT 
    [p].[shopper_id] 
    , [pi].[instrument_id] 
    , [ps].[style_id] 
FROM 
    [dbo].[profile] [p] 
INNER JOIN [dbo].[profile_instruments] [pi] 
ON [pi].[PID] = [p].[PID] 
INNER JOIN [dbo].[profile_styles] [ps] 
ON [ps].[PID] = [p].[PID] 
WHERE 
    [p].[date_created] > DATEADD(yy, -2, GETDATE()) 
    AND [p].[shopper_id] = '53D5444535434747A935E207C9EDD96A' 
ORDER BY 
    [p].[shopper_id]; 

我得到的結果:

shopper_id instrument_id style_id 
53D5444535434747A935E207C9EDD96A 35 845 
53D5444535434747A935E207C9EDD96A 35 291 
53D5444535434747A935E207C9EDD96A 17 845 
53D5444535434747A935E207C9EDD96A 17 291 

我沒有使用一組通過但因爲我不能確定如何將其應用於我擁有的專欄。我也不確定重複項是因爲我使用的連接類型,還是因爲我沒有使用羣組。

無論如何,我想尋求一些幫助,以便能夠找出我需要什麼修改我的查詢,以使有一個輸出,看起來像:

shopper_id instrument_id style_id 
53D5444535434747A935E207C9EDD96A 35 845 
53D5444535434747A935E207C9EDD96A 17 291 

謝謝提前尋求你的幫助。

+0

我們如何知道instrument_ID 35與style_ID 845而不是291?簡單地說,你錯過了一個定義這種關係的關聯。沒有它你會看到你看到的4個結果。所以在最後的加入你需要一個和PS。 = PI。表示哪種樂器與哪種風格的關係。如果無關緊要,您可以爲每條記錄分配一個行號並加入行號,但是這假設兩個表的每個購物者的記錄數相等。 – xQbert

+0

他們彼此獨立。配置文件和樂器以及配置文件和樣式之間有關係,但不在樂器和樣式之間。 –

+0

那麼我們怎麼知道35會轉到845而不是291?在這個例子中我再次看不到2條記錄的預期結果。如果它真的沒有關係,那麼行數概念可能會起作用;但它假定每個表中的記錄數相等,或者當每個購物者的記錄數不相等時,您需要使用外部聯接。 – xQbert

回答

2

也許......

我們指定一個行號,以每一款式和儀器每個PID。那麼我們不僅可以通過PID加入,我們可以通過Row_number加入,這保證了當pID有2個樂器和兩個風格時,我們仍然只能得到2個記錄;而不是4.

使用完整的外部連接,因爲我不知道是否想要查看存在2個樂器但僅存在1個樂器或2個樂器的情況。

SELECT [p].[shopper_id] 
    , [pi].[instrument_id] 
    , [ps].[style_id] 
FROM [dbo].[profile] [p] 
INNER JOIN (SELECT A.*, row_number() over (partition by PID order by instrument_ID) RN 
      FROM [dbo].[profile_instruments] A) [pi] 
    ON [pi].[PID] = [p].[PID] 
FULL OUTER JOIN (SELECT A.*, Row_number() over (partition by PID order by style_ID) RN 
       FROM [dbo].[profile_styles] A) [ps] 
    ON [ps].[PID] = [p].[PID] 
AND [PI].[RN] = [PS].[RN] 
WHERE [p].[date_created] > DATEADD(yy, -2, GETDATE()) 
    AND [p].[shopper_id] = '53D5444535434747A935E207C9EDD96A' 
ORDER BY [p].[shopper_id]; 

我們也許可以用在PI.RN一個COALESCE或PS.RN或兩個,如果你願意接受的是,當樣式和手段有不同的計數,在任一臺匹配到一個值接受

例子:

PID STYLE_ID  PID Instrument_ID 
1 A    1 Z 
1 B 

The above should return 
1 A Z 
1 B 

But maybe you want 
1 A Z 
1 B Z 

如果我們改變AND [PI].[RN] = [PS].[RN]AND coalesce([PI].[RN],1) = coalesce([PS].[RN],1)但是測試需要發生,這可能工作。就好像一方沒有pid的所有記錄,你仍然可以在一張桌子上得到空。

+0

嗨xQbert,當我嘗試使用你的例子時,它引發語法錯誤:Msg 102,Level 15,State 1,Line 7 'row_number'附近的語法錯誤。 Msg 156,Level 15,State 1,Line 10 關鍵字'over'附近的語法不正確。 –

+0

我在第二個子查詢的row_number之後缺少()。和第一個查詢中的逗號後面的逗號(thx SqlZim) – xQbert

+0

我應該注意,如果插入或更改了樣式或分期付款ID,則關聯可能會更改 – xQbert

0

嘗試進行自然連接,將類似於此:

SELECT 
    [p].[shopper_id], 
    [pi].[instrument_id], 
    [ps].[style_id] 
FROM 
    [dbo].[profile] [p], 
    [dbo].[profile_instruments] [pi], 
    [dbo].[profile_styles] [ps] 
WHERE 
    [p].[date_created] > DATEADD(yy, -2, GETDATE()) 
    AND [p].[shopper_id] = '53D5444535434747A935E207C9EDD96A' 
    AND [pi].[PID] = [p].[PID] 
    AND [ps].[PID] = [p].[PID] 
ORDER BY 
    [p].[shopper_id]; 
+0

樂器中的2個記錄*每個配置文件的2個樣式記錄產生4個記錄。我不明白這是怎麼回事。 – xQbert

+0

[踢壞的習慣:使用舊式JOIN - Aaron Bertrand](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style -joins.aspx) – SqlZim

+0

我認爲'自然連接'實際上使用了單詞'自然連接'和'使用'你在兩個表中定義了同樣命名的字段你想加入 – xQbert