比較兩個表之間的兩對列並從第三個表返回列
我有三張桌子:
表格1
table1
可以有 50K 到 800k 的唯一行。我的意思是每行中所有值的組合都是唯一的,儘管有時某些列會匹配。除了列之外,整行都可能匹配NAME
,但這是非常非常不可能的。NAME 列將始終是唯一的。該
NAME
列是 typevarchar(20)
。每條記錄的其餘列都是 typevarchar(6)
,其中每兩列是一個集合對,表有多達 21 個集合對(即總共 43 列)。這是一個table1
顯示 4 條記錄的一組對的範例(為了方便起見,我在這裡使用了單個字元,但不要忘記它們是 typevarchar(6)
):
table1
NAME pair1_1 pair1_2 ...up to pair21_1 - pair21_2 00001A A B 00002A A A 00003A B C 00004A A B …up to 800k rows
表2
table2
設置方式完全相同,只是它包含完全相同類型的完全不同的記錄(這裡可以有 1 到 200 行)
table2
NAME pair1_1 pair1_2 ...up to pair21_1 - pair21_2 1234B A B 5678B A A 9101B C C 1213B A B …up to 200 rows
表3
table3
與 in 中的單行相關聯,table2
並且可以表徵為該單行 intable2
與任何可能的行之間的比較的每個可能結果table1
。最好通過與它相關的NAME
in來呼叫table2
它(讓我們只使用第一個並呼叫它,table1234B
因為如果 table2 中有 200 行,則有 200 個不同的關聯table3
s)。第 3 個表將包含 4 行。它有一
NAME
列是 avarchar(20)
和 21 組 7 列(每列與 和 的不同對相關聯table1
)table2
。附加列res1_1
是res1_2…res21_7
typedecimal(30,7)
。這是它的樣子:
table1234B
NAME res1_1 res1_2 res1_3 res1_4 res1_5 res1_6 res1_7 ….res21_7 1234B 12.30 1.000 0.2500 1.000 2.000 2.10 25.00 ….
我想使用來自
table1
和的列對中的共享數據的組合table2
(即它們如何匹配)作為從中選擇數據的條件table1234B
(我將在下面展示其中的一些)。只會比較重合的對。pair1_1
andpair1_2
fromtable1
將與 topair1_1
和pair1_2
from進行比較table2
,pair2
s 將僅與pair2
s 進行比較,pair3
s 僅與pair3
s 進行比較等。因此,不會進行交叉對比較(例如pair1
,永遠不會與 進行比較pair2
)在下面的範例中,
pair1_1
每個表中的欄位匹配 (A),pair1_2
每個表中的欄位匹配 (B),但每個表的列之間的欄位不匹配。NAME Pair1_1 Pair1_2 00001A A B (from table1) 1234B A B (from table2)
所以我想 SELECT 說
pair1_4
fromtable1234B
並將其與記錄 00001A 和 1234B 之間的比較相關聯。如果表格是這樣的,我們可以看到所有 4 個欄位都匹配。
NAME pair1_1 pair1_2 00001A A A (from table1) 1234B A A (from table2)
在這種情況下,也許我想
pair1_1
選擇table1234B
在這裡我們可以看到
pair1_1
intable1
匹配兩個欄位 fromtable2
但pair1_2
fromtable1
不匹配任何內容。NAME pair1_1 pair1_2 00001A A B (from table1) 1234B A A (from table2)
所以我想選擇say
pair1_4
fromtable1234B
以上只是列對中的數據可以在表之間共享的 14 種可能方式中的 3 種(它們也有多種方式在表之間不共享數據),但每對只有 7 種可能的列可供選擇
table1234B
。我想從和
table1234B
的每組 2 中的列之間的所有可能共享中選擇符合標準的所有值。完成後看起來像這樣:table1``table2
1234BResult
NAME RESULTPair1 …up to Resultpair21 00001A 12.30 (res1_1 from table3) 00002B 1.000 (res1_2 from table3) 00003C 25.00 (res1_7 from table3) 00004A 1.000 (res1_4 from table3) …up to 800K rows
這是我開始編輯的查詢。
SELECT t1.NAME as NAME, t3.pair1_4 as RESULTPair1 FROM table1 t1 LEFT OUTER JOIN table2 t2 ON (t1.pair1_1 = t2.pair1_1 AND t1.pair1_1 <> t1.pair1_2 AND t1.pair1_2 = t2.pair1_2 AND t2.pair1_1 <> t2.pair1_2) LEFT OUTER JOIN table1234B t3 ON t2.NAME = t3.NAME
…以及該查詢的結果
NAME RESULTPair1 00001A 1.000 (res1_4 from table3) 00002B NULL 00003A NULL 00004A 1.000 (res1_4 from table3)
這更接近我正在尋找的內容,因為它使
NAME
stable2
具有不同的共享對來自 的其他值開放table1234B
。我打算合併後的剩餘邏輯將返回其他適當的結果。麻煩的是,這只會給我任何情況的結果,即 AB,AB。我需要將其擴展到 21 對和可能
table3
的 200 對,包括所有不同的可能結果(table3
如果適用)。我可以處理所有共享邏輯(即pair1_1 = pairt2_2
或pair1_1 <> pair2_2
),它將其擴展到其餘情況以及可能更多table2
我不知所措的記錄。我需要獲得table1
所有 21 對中所有 800k 記錄的結果。如果你和我待了這麼久並且理解所有的雞抓,我的問題是:
- 我將如何編輯上面的查詢以使用 a
JOIN
而不是 aWHERE
?- 是否有一種方法可以擴展它以有效地包含在欄位之間共享的其他可能場景的邏輯,
table1
以便table2
我可以在新表中查看或儲存從table1
單行到單行的所有 50-800k 結果table2
?- 我怎麼把它擴展到額外的 20 對?
編輯 在被問及與 table3 的連接後,我意識到該列需要編輯才能正常工作。我仍然無法弄清楚如何使查詢正常工作。我也編輯了查詢。我仍然在將其擴展到多個列時遇到了一些麻煩。建議使用 INTERSECT + EXCEPT 或 NOT EXISTS。我無法讓 INTERSECT 返回任何內容,而帶有編輯以包含左連接的查詢確實如此。
我有一個有效的查詢。它連接了 21 個派生表(比較的 21 對中的每一對都有一個)。它們是用 20
FULL OUTER JOIN
s 而不是LEFT JOIN
s 連接的,每個都有 14 個子查詢的集合和UNION ALL
s 組合,所以我將給出一個帶有一些評論的一般形式。它在 5 秒內完成了 67,000 次比較。SELECT COALESCE (t4.NAME, t5.NAME,...t25.NAME) AS NAME, t4.RESULTPair1, t5.RESULTPair2,...t25.RESULTPair21 FROM ((SELECT t1.NAME AS NAME, t3.RESULTPair1_1 AS RESULTPair1 FROM table1 t1 INNER JOIN table2 t2 ON (t1.pair1_1 = t1.pair1_2 AND ---logic between table1 and table2 for AAAA t1.pair1_1 = t2.pair1_1 AND t1.pair1_1 = t2.pair1_2) INNER JOIN table1234B t3 ON t2.NAME = t3.NAME) UNION ALL (SELECT t1.NAME AS NAME, t3.RESULTPair1_2 AS RESULTPair1 FROM table1 t1 INNER JOIN table2 t2 ON (---LOGIC FOR AAAB---) ---I wont bore you with the rest of the matching logic unless someone is really interested INNER JOIN table1234B t3 ON t2.NAME = t3.NAME) ------Repeat the above query for each set of logic AAAB, AABA, ABAA, BAAA etc. with 13 ------total UNION ALL (each set of logics will take care of every possible situation of ------sharing between the tables and each t1.NAME is different so UNION ALL will be more ------efficient, COALESCE for the NAME field returns a full column for NAME) UNION ALL (SELECT t1.NAME AS NAME, t3.RESULTPair1_7 AS RESULTPair1 FROM OFFENDERS t1 INNER JOIN table2 t2 ON (---LOGIC FOR AABB---) INNER JOIN table1234B t3 ON t2.NAME = t3.NAME)) t4 --aabb ——-now move through the remaining result pairs up to 21 (ie derived table25) FULL OUTER JOIN ——-subqueries for result set2 ON t4.NAME = t5.NAME ——-subqueries for resultsets 3-20 ON t23.NAME = t24.NAME FULL OUTER JOIN ((SELECT t1.NAME AS NAME, t3.RESULTPair21_1 AS RESULTPair21 FROM table1 t1 INNER JOIN table2 t2 ON (---LOGIC FOR AAAA---) INNER JOIN table1234B t3 ON t2.NAME = t3.NAME) ---aaaa UNION ALL -------remaining sets of logic for RESULTPair21 SELECT t1.NAME AS NAME, t3.RESULTPair21_7 AS RESULTPair21 FROM table1 t1 INNER JOIN table2 t2 ON (---LOGIC FOR AABB---) INNER JOIN table3 t3 ON t2.NAME = t3.NAME)) t25 --aabb ON t24.NAME = t25.NAME
這是一項正在進行的工作,所以如果我可以做些什麼來改進它,請告訴我!就像我在上面的評論中所說的那樣,我想我要設置另一個表來將 varchar(6) 欄位索引為整數,然後使用整數進行比較。所以現在 table1 和 table2 看起來像這樣:
table1 NAME pair1_1 pair1_2 ...up to pair21_1 - pair21_2 00001A 1 2 00002A 1 1 00003A 2 3 00004A 1 2 …up to 800k rows table2 NAME pair1_1 pair1_2 ...up to pair21_1 - pair21_2 1234B 1 2 5678B 1 1 9101B 3 3 1213B 1 2 …up to 200 rows
…以及使比較更快的附加索引,以防我想檢索實際的數據集:
intIndex pairs code A 1 B 2 C 3 D 4 ... up to all possible varchar(6) character strings
我添加了索引表,現在可以比較整數而不是 varchar(6) 列。67,000 table1 行查詢在 5 秒內為 varchar(6) 列生成 21 列,而對於整數列則為 4 秒。140 萬次計算。有人有任何其他建議可以幫助我嗎?