2011-05-07 78 views
1

我有兩個表:一個包含電子郵件,另一個包含域。MySQL SELECT行部分匹配其他表中的字符串

Table1     Table2 
id email    id domain 
-- ----     -- ---- 
1 [email protected]  1 domain1.com 
2 [email protected]  2 domain4.com 
3 [email protected] 
4 [email protected] 

現在我要選擇從表1中的所有電子郵件,其中域表2的場域匹配的結果應該是:

id email 
-- ---- 
1 [email protected] 
4 [email protected] 

我想這將與REGEXP的組合工作和INNER JOIN?但我不知道如何組合它們。

回答

3

解決方案1:

使用Table1.email LIKE CONCAT('%@',Table2.domain).

大發紅色預警:這種情況是不是可轉位。如果您想要速度,請將電子郵件分成表1中的地址和域,然後創建一個索引。

編輯:

事實上,這JOIN條件將需要數(電子郵件)XCOUNT(域)的比較,因此它可能是最慢的方式。

解決方案2:

羅布具有非常好的點:一個更快的方法是提取從電子郵件域(使用子串)和符合此針對在域表的索引

溶液3:

最好的方法是索引電子郵件的域名。在Postgres中,你可以創建一個函數索引ON extract_domain(email)(假設你創建了一個簡單的extract_domain()函數),但是你不能在MySQL中這樣做,所以只有域的額外列纔是提高速度的方法。

如果你想知道在一個域中的所有電子郵件,

Solution 1 : seq scan table emails + fast LIKE 
Solution 2 : seq scan table emails + slightly slower domain extraction 
Solution 3 : index scan table emails 

如果您想加入上表中域的所有域/所有電子郵件:

Solution 1 : count(email)xcount(domain) comparisons, very slow 
Solution 2 : seq scan table emails + index scan domains 
Solution 3 : nested loop index join 

對於一個完整的JOIN會更快地使用合併連接或散列連接,但這些不是由mysql提供的。

+0

怎麼樣SUBSTRING_INDEX(Table1.email, '@',-1 )= Table2.domain 帶有Table2.domain上的索引? – Rob 2011-05-07 22:37:25

+0

Table2.Domain上的索引可能提供無關緊要的優勢,因爲域的列表將比電子郵件列表小得多。 – 2011-05-07 22:39:57

+0

@Rob:對錶列的任何操作都會導致索引無用,因爲要比較的數據與索引所包含的數據不同。 – 2011-05-07 23:21:29

2

嘗試了這一點

SELECT t1.Id, 
     t1.Email 
    FROM Table1 t1 
    JOIN Table2 t2 ON t1.email LIKE CONCAT('%@', t2.Domain); 
+0

AFAIK您需要在'MySQL'中使用'CONCAT' – 2011-05-07 22:47:12

+0

@Martin:不,MySQL不需要CONCAT來連接字符串。對於這一點,Oracle也不例外。 – 2011-05-07 23:15:00

+0

啊我確定我記得當我用'+'將它們轉換爲數字時它會返回'0'。也許其他一些其他的RDBMS。 – 2011-05-07 23:31:23

4

我創建表,做了一個試驗,這個查詢工作對我來說:

SELECT t1.*, t2.domain FROM t1 
INNER JOIN t2 ON t1.email LIKE CONCAT('%@', t2.domain); 
+0

你是對的我的朋友,抱歉我的錯誤。我編輯了我的答案。 – PachinSV 2011-05-08 00:29:07

+0

+1:感謝您使用ANSI-92 JOIN語法:) – 2011-05-08 00:55:18