我需要一个数据库中的用户列表,这些用户未在另一个数据库中列为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条记录?
注意以上查询是对我真正追求的简化。还有其他/更好的方法来执行上述查询...它们只是代表查询中给我带来问题的部分。
答案 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
查询的行为感兴趣,请道歉