2

假设我有table1这样的:

id | itemcode
-------------
1  | c1
2  | c2
...

table2这样:

item | name
-----------
c1   | acme
c2   | foo
...

以下两个查询会在每种条件下返回相同的结果集吗?

SELECT id, itemcode 
FROM table1 
WHERE itemcode IN (SELECT DISTINCT item 
                  FROM table2 
                  WHERE name [some arbitrary test])

SELECT id, itemcode 
FROM table1 
   JOIN (SELECT DISTINCT item 
          FROM table2
          WHERE name [some arbitrary test]) items 
         ON table1.itemcode = items.item

除非我真的错过了一些愚蠢的东西,否则我会说是的。但是我做了两个查询,归结为这种形式,我得到了不同的结果。有一些使用 WHERE IN 的嵌套查询,但对于最后一步,我注意到 JOIN 更快。嵌套查询都是完全隔离的,所以我不认为它们是问题,所以我只是想消除我对上述内容有误解的可能性。

感谢您的任何见解。

编辑

两个原始查询:

SELECT imitm, imlitm, imglpt 
    FROM jdedata.F4101 
    WHERE imitm IN 
  (SELECT DISTINCT ivitm AS itemno 
       FROM jdedata.F4104 
       WHERE ivcitm IN 
    (SELECT DISTINCT ivcitm AS legacycode 
             FROM jdedata.F4104 
              WHERE ivitm IN 
      (SELECT DISTINCT tritm 
               FROM trigdata.F4101_TRIG)
    )
  )


SELECT orig.imitm, orig.imlitm, orig.imglpt 
    FROM jdedata.F4101 orig 
        JOIN 
        (SELECT DISTINCT ivitm AS itemno 
        FROM jdedata.F4104 
        WHERE ivcitm IN 
              (SELECT DISTINCT ivcitm AS legacycode 
              FROM jdedata.F4104
               WHERE ivitm IN 
                 (SELECT DISTINCT tritm 
                  FROM trigdata.F4101_TRIG))) itemns 
ON orig.imitm = itemns.itemno

编辑 2

虽然我仍然不明白为什么查询会返回不同的结果,但似乎我们的逻辑从一开始就存在缺陷,因为我们在某些部分使用了错误的列。请注意,我并不是说我在解释上面写的查询时犯了错误或有一些错字,我们只需要选择一些不同的东西。

通常我不会在弄清这些事情的底部之前休息,但我很累,并且正在进入自一月份以来的第一个假期,跨越一天以上,所以我现在真的懒得再去寻找了. 我相信这里给出的提示稍后会派上用场。已为所有帮助分发了赞成票,我接受了 Ypercube 的回答,主要是因为他的评论让我走得最远。但是谢谢大家!如果我稍后发现更多信息,我会尽量记住 ping 回来。

4

5 回答 5

4

由于table2.item不可为空,因此 2 个版本是等效的。您可以distinctIN版本中删除,它不是必需的。您可以查看这 3 个版本及其执行计划:

SELECT id, itemcode FROM table1 WHERE itemcode IN
  ( SELECT item FROM table2 WHERE name [some arbitrary test] )

SELECT id, itemcode FROM table1 JOIN
  ( SELECT DISTINCT item FROM table2 WHERE name [some arbitrary test] )
  items ON table1.itemcode = items.item

SELECT id, itemcode FROM table1 WHERE EXISTS
  ( SELECT * FROM table2 WHERE table1.itemcode = table2.item 
                           AND (name [some arbitrary test]) )
于 2011-08-24T12:14:58.560 回答
1

理想情况下,我希望看到结果集之间的差异。
- 您是否得到重复记录
- 一组是否总是另一组的子集
- 一组与另一组相比是否同时具有“附加”和“缺失”记录?

也就是说,逻辑应该是等价的。我最好的猜测是那里有一些空字符串条目;因为 Oracle 的 NULL CHAR/VARCHAR 版本只是一个空字符串。如果您没有为此做好准备,这可能会产生非常时髦的结果。

于 2011-08-24T13:14:04.537 回答
1

两个查询都执行半连接,即没有属性table2出现在最顶层SELECT(结果集)。

在我看来,您的第一个查询最容易识别为半联接,EXISTS更是如此。另一方面,优化器无疑会以不同的方式看待它;)

于 2011-08-24T13:16:06.660 回答
1

您也可以尝试直接连接到第二个表

SELECT DISTINCT id, itemcode 
FROM table1 
INNER JOIN table2 ON table1.itemcode = table2.item   
WHERE name [some arbitrary test] )

如果 item 是主键或唯一的,则不需要distinct

ExistsInner Join应该具有相同的执行速度,而IN更昂贵。

于 2011-08-24T13:27:15.473 回答
1

我会在那里寻找一些数据类型转换。

create table t_vc (val varchar2(6));
create table t_c (val char(6));

insert into t_vc values ('12345');
insert into t_vc values ('12345 ');

insert into t_c values ('12345');
insert into t_c values ('12345');

select t_c.val||':'
from t_c
where val in (select distinct val from t_vc);

select c.val||':'
from t_vc v join (select distinct val from t_c) c on v.val=c.val;
于 2011-08-25T05:00:33.213 回答