2010-02-20 66 views
6

這是我的查詢:SQL:語法錯誤與intersect?

-- Sids of suppliers who supply a green part AND a red part 
(SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color = "red") 
INTERSECT 
(SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color = "green"); 

這是錯誤:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "INTERSECT (SELECT Suppliers.sid FROM Suppliers JOIN Catalog ON Catalog.sid = Sup" on line 6.

我在做什麼錯?

這是架構:

的供應商(SID:整數,SNAME:串,地址字符串)

零件(PID:整數,PNAME:字符串,顏色:字符串)

目錄(SID:整數,PID:整數,成本:真正的)

大膽 =主鍵

回答

6

MySQL中,你似乎使用,不支持INTERSECT語法。你將不得不以另一種方式解決它。

在這種情況下,它是微不足道的 - 我們只需要一個提供某些部分的「綠色」和「紅色」的所有供應商列表 - 您的查詢並不費心去查看這些部分本身是否相關,所以我們可以解決這個問題很容易像這樣:

SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color IN ('red', 'green') 
GROUP BY Suppliers.sid 
HAVING COUNT(DISTINCT Parts.color) = 2 

就個人而言,我不認爲原來的查詢是典型的INTERSECT問題。看看Vinko Vrsalovic提供的JOIN解決方案,以獲得一個通用解決方案來模擬INTERSECT(即使RDBMS實際上本身會提供INTERSECT,我也會更喜歡它)

+0

看看哪個更快,這個查詢或我的查詢會很有趣 - 我認爲這是更快的,第二次加入或按操作分組。 – Hogan 2010-02-20 17:03:06

+0

@Hogan,* shrug *。這取決於如此多的東西:索引,引擎,多少行,多少內存。無可挑剔的名單......如果問題是找到最快的解決方案,我會採取完全不同的方法來回答這個問題。目前,我處於如下模式:如何重寫標準SQL以獲得等效結果,以防MySQL不支持語法。 – 2010-02-20 17:07:27

+0

點,我想我總是在最快的模式,而不是最明顯的。 – Hogan 2010-02-20 17:42:14

2

這應該做你想要什麼:

SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
INNER JOIN Parts AS parts1 ON parts1.pid = Catalog.pid AND parts1.color = "red" 
INNER JOIN Parts AS parts2 ON parts2.pid = Catalog.pid AND parts2.color = "green" 
+0

我不認爲這是這種情況下的問題。 'INTERSECT'只是不被MySQL支持。 – 2010-02-20 16:53:21

+0

並且該查詢將無法執行。OP希望所有sids都有綠色和紅色部分。您的查詢將返回所有sids,並顯示綠色或紅色部分。 – 2010-02-20 16:55:09

+0

@Roland,@Vinko:是的,我看到了,我確定了答案,這應該做他想做的事,並且比子查詢更快。 – Hogan 2010-02-20 16:57:42

4

Nothing,MySQL沒有INTERSECT關鍵字。你可以把它改寫爲INNER JOIN:

SELECT DISTINCT sid FROM 
(SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color = "red") a 
INNER JOIN 
(SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color = "green") b 
ON (a.sid = b.sid); 

這種查詢可以肯定更好的寫法,但是這是要表明,交叉只是有選擇不同的僅僅是一個內部聯接,可以自動變換到彼此。

+0

我大多同意,但是'INTERSECT'和'INNER JOIN'不完全一樣。 'INTERSECT'默認爲'INTERSECT DISTINCT',這意味着它只需要返回唯一的行。在實際的情況下,也可能在這種情況下,它只會工作,但要獲得真正的重寫,你必須添加「DISTINCT」或「GROUP BY」 – 2010-02-20 17:11:10

+0

@Roland:感謝您的註釋,我編輯以反映它。 – 2010-02-20 17:16:36

+0

都很酷。你現在正在創建+1,因爲我基本上認爲'JOIN'比'INTERSECT'好很多:)只有我見過相交的時間,在SQL作業分配中;) – 2010-02-20 17:23:28

0

爲了在MySQL中使用INTERSECT的另一個解決方案是使用IN子句。問題:「尋找2009年秋季開設的課程當然id和 2010年春季」

//DML sample 
(select course_id 
from section 
where semester = ‘Fall’ and year = ‘2009’) 
intersect 
(select course_id 
from section 
where semester = ‘Spring’ and year = ‘2010’); 

在MySQL:

select distinct course_id 
from section 
where semester = 'Fall' and year= 2009 and 
course_id in (select course_id 
from section 
where semester = 'Spring' and year= 2010); 

如果你需要更多的IN條款,請在谷歌搜索。