2010-02-20 68 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条款,请在谷歌搜索。