SQL单行子查询returns多行?
SQL single-row subquery returns more than one row?
我正在尝试从一个查询中获取 ID 和 USER 名称,但同时我正在查找我的 WHERE 子句中是否存在其他 table 中的 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 子句 returns 内的查询有两个 ID:158 和 159,因此我在查找 s.ID 和 s.LASTFIRST 的查询中不应返回这两个 ID。什么可能导致此错误?
使用not in
代替!=
!=
或 =
用于单个 ID 和值,not in
和 in
用于多个
And s.ID not in (SELECT USER_ID
From RESERVATIONS
Where EVENT_ID = '56')
编辑:not in
对比 not exists
Not exists
也是一个完全可行的选择。事实上,如果子查询结果集中有null
值的可能性,not exists
比not in
更好——在Oracle中,null
的存在会导致not in
到 return 没有结果。作为一般规则,我对 ID 使用 not in
,而不是空列,对其他所有内容使用 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's optimizer is able to see that NOT EXISTS, NOT IN and LEFT JOIN / IS NULL are semantically equivalent as long as the list values are declared as NOT NULL.
It uses same execution plan for all three methods, and they yield same results in same time.
这是一条与您的问题无关的格式化评论。
这很慢:
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
)
我正在尝试从一个查询中获取 ID 和 USER 名称,但同时我正在查找我的 WHERE 子句中是否存在其他 table 中的 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 子句 returns 内的查询有两个 ID:158 和 159,因此我在查找 s.ID 和 s.LASTFIRST 的查询中不应返回这两个 ID。什么可能导致此错误?
使用not in
代替!=
!=
或 =
用于单个 ID 和值,not in
和 in
用于多个
And s.ID not in (SELECT USER_ID
From RESERVATIONS
Where EVENT_ID = '56')
编辑:not in
对比 not exists
Not exists
也是一个完全可行的选择。事实上,如果子查询结果集中有null
值的可能性,not exists
比not in
更好——在Oracle中,null
的存在会导致not in
到 return 没有结果。作为一般规则,我对 ID 使用 not in
,而不是空列,对其他所有内容使用 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's optimizer is able to see that NOT EXISTS, NOT IN and LEFT JOIN / IS NULL are semantically equivalent as long as the list values are declared as NOT NULL.
It uses same execution plan for all three methods, and they yield same results in same time.
这是一条与您的问题无关的格式化评论。
这很慢:
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
)