Sql “平等”;选择。。。“在哪里?”;并加入

Sql “平等”;选择。。。“在哪里?”;并加入,sql,oracle,join,sql-in,semi-join,Sql,Oracle,Join,Sql In,Semi Join,假设我有一个表1,如下所示: id | itemcode ------------- 1 | c1 2 | c2 ... item | name ----------- c1 | acme c2 | foo ... 还有一个表2,如下所示: id | itemcode ------------- 1 | c1 2 | c2 ... item | name ----------- c1 | acme c2 | foo ... 以下两个查询是否会在每个条件下返回相同的

假设我有一个
表1
,如下所示:

id | itemcode
-------------
1  | c1
2  | c2
...
item | name
-----------
c1   | acme
c2   | foo
...
还有一个
表2
,如下所示:

id | itemcode
-------------
1  | c1
2  | c2
...
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,但在最后一步中,我注意到连接要快得多。嵌套查询都是完全孤立的,所以我不认为它们是问题所在,所以我只想消除我对上述内容有误解的可能性

谢谢你的见解

编辑

两个原始查询:

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

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


通常情况下,我在弄清这些事情的真相之前不会休息,但我非常累,即将进入自1月份以来的第一个假期,这一假期跨越了一天多的时间,所以我现在真的不想再费心寻找更多的东西了。我相信这里给出的提示稍后会派上用场。所有的帮助都得到了投票,我接受了Ypercube的回答,主要是因为他的评论让我走得最远。谢谢大家!如果我以后确实发现了更多信息,我会尽量记住ping返回。

因为
表2.item
不可为空,这两个版本是等效的。您可以从版本中的中删除不同的,不需要它。您可以检查这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]) )

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

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

两个查询都会执行一个操作,即
表2
中的属性不会出现在最顶端的
选择(结果集)中


在我看来,您的第一个查询最容易识别为半连接,
存在
更是如此。另一方面,优化器无疑会有不同的看法;)

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

SELECT DISTINCT id, itemcode 
FROM table1 
INNER JOIN table2 ON table1.itemcode = table2.item   
WHERE name [some arbitrary test] )
如果项是主键或唯一项,则不需要使用distinct


存在内部联接应该具有相同的执行速度,而中的更昂贵。

我会在其中寻找一些数据类型转换

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;

您的示例查询应该返回相同的结果。您可以发布您真正正在运行的查询吗?您还可以使用
EXISTS
重写查询。我认为如果
表1.itemcode
表2.item
是字符类型,并且表中有空字符串,则可能会解释为什么不显示相同的结果桌子。是这样吗?这是一个很好的观点!这些表确实使用CHAR而不是VARCHAR,并且在处理结果时,我们还需要修剪一些空白。最好的线索,所以,我会去检查一些特定的行。
in
中的+1-
DISTINCT
存在子查询让我发疯。感谢您指出这一点。只有当您不想从结果集中的子查询返回任何字段时,它们才是等效的,然后您需要一个联接。