我正在尝试从一个查询中获取ID和USER名称,但同时我正在查看我的WHERE子句,如果其他表中存在ID。我收到了错误:
ORA-01427: single-row subquery returns more than one row
以下是我的查询的外观:
SELECT s.ID, s.LASTFIRST
From USERS s
Left Outer Join CALENDAR c
On s.ID = c.USERID
Where c.SUPERVISOR = '103'
And TO_CHAR(c.DATEENROLLED,'fmmm/fmdd/yyyy') >= '4/22/2016'
And TO_CHAR(c.DATELEFT,'fmmm/fmdd/yyyy') <= '4/22/2016'
And s.ID != (SELECT USER_ID
From RESERVATIONS
Where EVENT_ID = '56')
我在where子句中的查询返回两个ID:158和159所以这两个不应该在我的查询中返回,我正在寻找s.ID和s.LASTFIRST。什么可能导致此错误?
答案 0 :(得分:4)
使用not in
代替!=
!=
或=
适用于单个ID和值,not in
和in
适用于多个
And s.ID not in (SELECT USER_ID
From RESERVATIONS
Where EVENT_ID = '56')
修改:not in
vs not exists
Not exists
也是一个完全可行的选择。实际上,如果子查询结果集中存在not exists
值的可能性,则not in
比null
更好 - 在Oracle中,null
的存在将导致not in
不返回任何结果。作为一般规则,我使用not in
表示ID,而不是空列,not exists
表示其他所有内容。最好始终使用not exists
...个人偏好我认为。
Not exists
会这样写:
SELECT s.ID, s.LASTFIRST
From USERS s
Left Outer Join CALENDAR c
On s.ID = c.USERID
Where c.SUPERVISOR = '103'
And TO_CHAR(c.DATEENROLLED,'fmmm/fmdd/yyyy') >= '4/22/2016'
And TO_CHAR(c.DATELEFT,'fmmm/fmdd/yyyy') <= '4/22/2016'
And not exists (SELECT USER_ID
From RESERVATIONS r
Where r.USER_ID = S.ID
And EVENT_ID = '56')
<强>性能强>
在Oracle中,使用not in
,not exists
或left join
之间没有性能差异。
来源:https://explainextended.com/2009/09/17/not-in-vs-not-exists-vs-left-join-is-null-oracle/
Oracle的优化器能够看到NOT EXISTS,NOT IN和LEFT JOIN / IS NULL在语义上是等效的,只要列表值被声明为NOT NULL。
它对所有三种方法使用相同的执行计划,并且它们同时产生相同的结果。
答案 1 :(得分:2)
这是与您的问题无关的格式化评论。
这很慢:
And TO_CHAR(c.DATEENROLLED,'fmmm/fmdd/yyyy') >= '4/22/2016'
因为您正在过滤函数结果。
这在逻辑上相当且更快:
And c.DATEENROLLED >= to_date('4/22/2016','fmmm/fmdd/yyyy')
编辑从此处开始
Aaron D的回答是使用not in
。以下是两种更快速的方法:
left join reservations r on s.id = user_id
and r.event_id = '56'
etc
where r.user_id is null
或
where s.id in
(
select user_id
from reservations
minus
select user_id
from reservations
where event_id = 56
)