我使用Mysql中的以下代码定义了表PARTS,CATALOG和PLIST:
create table parts (
PID int
);
create table catalog(
SID varchar(3),
PID int
);
create table plist(
PID int
);
insert into parts values (1),(2),(3), (4);
insert into catalog values
("A", 1), ("A", 2), ("A", 4),
("B", 2), ("B", 3), ("B", 4),
("C", 1), ("C", 4),
("D", 2), ("D", 3);
insert into plist values (2), (4);
我想执行关系除法运算符目录plist。关系除法运算符在SQL中不可用。以下实现在Oracle中成功运行:
SELECT DISTINCT(SID) FROM CATALOG A WHERE NOT EXISTS
(SELECT PID FROM PLIST MINUS SELECT PID FROM CATALOG WHERE SID = A.SID);
现在,在MYsql中,MINUS运算符不可用。以下查询在Mysql中成功实现了上面使用的MINUS操作(引入了一个独立测试查询的修改)。
SELECT B.PID FROM PLIST LEFT JOIN
(SELECT PID FROM CATALOG WHERE SID = "C") B ON B.PID=PLIST.PID
WHERE B.PID IS NULL;
但是,当我使用上面的代码作为子查询来实现关系除法运算符
时SELECT DISTINCT(SID) FROM CATALOG WHERE NOT EXISTS
( SELECT B.PID FROM PLIST LEFT JOIN
(SELECT A.PID FROM CATALOG A WHERE A.SID = SID) B ON B.PID = PLIST.PID
WHERE B.PID IS NULL
);
我没有得到预期的结果。预期结果包含SID值" A"和" B"只要。但是,上面代码生成的结果包含所有四个SID值。这很奇怪,因为当独立测试时,子查询会产生正确的结果(如果SID等于" A"或" B"以及其他两个SID值非空,则为空)。
如果这个奇怪的行为是由这个论坛的某个人解释的,我将感激不尽。
非常感谢您的期待。
答案 0 :(得分:0)
行为解释如下:
我写的查询是错误的,因为在内部查询中,A.SID和SID之间没有区别。因此,条件总是导致TRUE。
因此,作为相关子查询的意图并非如此。
这解释了为什么查询结果包含所有四个SID。
但是,正如我在第一条评论中所述,当我在外部查询中使用表的别名时,并在内部查询中使用该别名,如下所示
SELECT DISTINCT(SID) FROM CATALOG A WHERE NOT EXISTS
( SELECT B.PID FROM PLIST LEFT JOIN
(SELECT PID FROM CATALOG WHERE SID = A.SID) B ON B.PID = PLIST.PID
WHERE B.PID IS NULL
);
我收到错误:where子句中的未知列“A.SID”。
我不明白为什么别名A不在子查询的范围内。