当用作子查询时,Mysql查询会产生不同的结果

时间:2015-09-25 08:29:35

标签: mysql correlated-subquery

我使用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值非空,则为空)。

如果这个奇怪的行为是由这个论坛的某个人解释的,我将感激不尽。

非常感谢您的期待。

1 个答案:

答案 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不在子查询的范围内。