不在查询...奇怪的结果

时间:2012-10-19 21:15:31

标签: oracle notin

我需要一个数据库中的用户列表,这些用户未在另一个数据库中列为new_user_id。两个数据库中有112,815个匹配用户; user_id是所有查询表中的关键。


查询#1有效,并为我提供了111,327个未被引用为new_user_Id的用户。但它需要两次查询相同的数据。

-- 111,327 GSU users are NOT listed as a CSS new user 
--   1,488 GSU users ARE listed as a new user in CSS
--
select count(gup.user_id)
from   gsu.user_profile gup
  join (select cud.user_id, cud.new_user_id, cud.user_type_code
        from   css.user_desc cud) cudsubq
    on gup.user_id = cudsubq.user_id
where  gup.user_id not in (select cud.new_user_id 
                           from   css.user_desc cud
                           where  cud.new_user_id is not null);


查询#2将是完美的......我真的很惊讶它在语法上被接受了。但它给了我一个毫无意义的结果。

-- This gives me 1,505 users... I've checked, and they are not
-- referenced as new_user_ids in CSS, but I don't know why the ones 
-- that were excluded were excluded.
--
-- Where are the missing 109,822, and whatexcluded them?
-- 
select count(gup.user_id)
from   gsu.user_profile gup
  join (select cud.user_id, cud.new_user_id, cud.user_type_code
        from   css.user_desc cud) cudsubq
    on gup.user_id = cudsubq.user_id
where  gup.user_id not in (cudsubq.new_user_id);


第二个查询中的where子句到底是做什么的,为什么从结果中排除109,822条记录?


注意以上查询是对我真正追求的简化。还有其他/更好的方法来执行上述查询...它们只是代表查询中给我带来问题的部分。

4 个答案:

答案 0 :(得分:4)

阅读本文:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:442029737684

根据我的理解,即使两个表都由cudsubq.new_user_id加入,您的NULL也可以是user_id,因此,您将无法使用{{1}获得结果子集包含NOT IN时的运算符。考虑一下文章中的例子:

NULL

这不会返回任何记录。尝试使用select * from dual where dummy not in ( NULL ) 运算符或仅使用其他类型的联接。这是一个很好的来源:http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

你需要的是第四个例子:

NOT EXISTS

答案 1 :(得分:1)

第二个查询在语义上是不同的。在这种情况下

where  gup.user_id not in (cudsubq.new_user_id)

cudsubq.new_user_id被视为表达式(doc: IN condition),而不是子查询,因此整个子句基本等同于

where  gup.user_id != cudsubq.new_user_id

因此,在您的第一个查询中,您真的要求"向我展示GUP中的所有用户,他们在CSS中也有条目,并且他们的GUP.ID与ANY NOT NULL不匹配#34;中的em> NEW_ID。

然而,第二个查询是"显示GUP中的所有用户,他们也有CSS条目,他们的GUP.ID不等于他们的RESPECTIVE NULLABLE (no {{1记住吗?)CSS.NEW_ID值​​"。

任何使用空值的is not null(或等式/不等式)检查实际上都不起作用。

(not) in

这是您丢失行的地方。我可能会将你的第二个查询重写为where子句 12:07:54 SYSTEM@oars_sandbox> select * from dual where 1 not in (null, 2, 3, 4); no rows selected Elapsed: 00:00:00.00 ,假设不匹配的用户为null new_user_id。

答案 2 :(得分:0)

您的第二个选择将gup.user_id与当前加入记录上的cud.new_user_id进行比较。您可以重写查询以获得相同的结果

select count(gup.user_id)
from   gsu.user_profile gup
  join (select cud.user_id, cud.new_user_id, cud.user_type_code
        from   css.user_desc cud) cudsubq
    on gup.user_id = cudsubq.user_id
where  gup.user_id != cud.new_user_id or cud.new_user_id is null;

您提到将一个数据库中的用户列表与另一个数据库中的用户列表进行比较。因此,您需要两次查询数据,而不是查询相同的数据。也许你可以使用“减”运算符来避免使用“in”

select count(gup.user_id)
from   gsu.user_profile gup
  join (select cud.user_id from css.user_desc cud
        minus
        select cud.new_user_id from css.user_desc cud) cudsubq
    on gup.user_id = cudsubq.user_id;

答案 3 :(得分:0)

您希望表new_user_id中的gup与表new_user_id上的任何cud都不匹配,对吗?这听起来像是左联盟的工作:

SELECT count(gup.user_id)
    FROM gsu.user_profile gup LEFT JOIN css.user_desc cud
        ON gup.user_id = cud.new_user_id
    WHERE cud.new_user_id is NULL

联接保留gup的所有行,如果可能,将其与new_user_id匹配。 WHERE条件仅保留cud中没有匹配行的行。

(如果您已经知道并且您只对not in查询的行为感兴趣,请道歉