3

我需要一个数据库中未在另一个数据库中列出的用户列表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

4 回答 4

4

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

据我了解,即使两个表都由 连接,您cudsubq.new_user_id也可以,因此,当子集包含values时,您将不会使用运算符获得结果。考虑文章中的示例:NULLuser_idNOT INNULL

select * from dual where dummy not in ( NULL )

这不返回任何记录。尝试使用NOT EXISTS运算符或只是另一种联接。这是一个很好的来源: http: //www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

你需要的是第四个例子:

SELECT COUNT(descr.user_id)
FROM 
    user_profile prof
    LEFT OUTER JOIN user_desc descr
        ON prof.user_id = descr.user_id 
WHERE descr.new_user_id IS NULL
    OR descr.new_user_id != prof.user_id
于 2012-10-29T18:06:31.167 回答
1

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

where  gup.user_id not in (cudsubq.new_user_id)

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

where  gup.user_id != cudsubq.new_user_id

因此,在您的第一个查询中,您实际上是在询问“向我展示 GUP 中的所有用户,他们在 CSS 中也有条目,并且他们的 GUP.ID 与 CSS 中的 ANY NOT NULL NEW_ID 不匹配”。

但是,第二个查询是“显示 GUP 中的所有用户,他们在 CSS 中也有条目,并且他们的 GUP.ID 不等于他们的 RESPECTIVE NULLABLE(没有is not null子句,记得吗?) CSS.NEW_ID 值”。

并且任何(not) in(或相等/不等式)带有空值的检查实际上都不起作用。

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          

这是您丢失行的地方。where cudsubq.new_user_id is null假设不匹配的用户的 new_user_id 为空,我可能会将您的第二个查询的 where 子句重写为 。

于 2012-10-30T04:10:29.640 回答
0

你想要new_user_id's from table 与 table上的任何内容gup都不匹配,对吧?这听起来像是左连接的工作:new_user_idcud

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,将它们与 a 匹配。new_user_idWHERE 条件仅保留 中没有匹配行的行cud

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

于 2012-10-29T21:47:52.533 回答
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;
于 2012-10-24T04:32:31.560 回答