繁体   English   中英

Oracle:如何使用左外部联接从左表获取所有条目并满足Where子句中的条件

[英]Oracle: How to use left outer join to get all entries from left table and satisfying the condition in Where clause

我有下表。

客户:

ID | clientName
--------------
1    A1        
2    A2
3    A3          

订购:

OrdID clientID status_cd
------------------------
100  1        DONE
101  1        SENT
102  3       SENT

状态:

status_cd  status_category
DONE        COMPL
SENT        INPROG

我必须编写一个查询来获取所有客户端以及针对所有客户端的订单计数,无论client_id是否存在于Order表中以及是否具有“ COMPL”作为状态类别的订单。

在这种情况下,我使用下面的查询,但是它过滤掉了没有订单的客户。 我希望获得所有客户,以使预期结果如下。

查询:

select c.ID, count(distinct o.OrdID) 
from client c, order o, status s
where c.ID=o.client_id(+)
and o.status_cd=s.status_cd where s.status_category='COMPL'
group by c.ID

预期结果:

C.ID   count(distinct o.OrdID)
---------------------------- 
1       1
2       0
3       0

有人可以帮我吗? 我知道,在这种情况下,当我使用where子句时,左外部联接的行为类似于内部联接,但是还有其他方法可以实现上述结果吗?

使用显式联接运算符时,这可以轻松得多:

select c.ID, count(distinct s.status_cd) 
from client c
  left join orders o on o.clientid = c.id
  left join status s on s.status_cd = o.status_cd and s.status_category='COMPL'
group by c.ID;

上面假设orders.status_cd定义为not null

另一种选择是在派生表中的订单和状态之间移动联接:

select c.ID, count(distinct o.ordid) 
from client c
  left join (
    select o.ordid
    from orders o
      join status s on s.status_cd = o.status_cd
    where s.status_category='COMPL'
  ) o on o.clientid = c.id
group by c.ID;

上面的“声明”更清楚地(至少在我看来)是,与第一个解决方案相比,仅关注该状态类别中的订单

和往常一样,有很多方法可以表达这一要求。

尝试ANSI加入人们会讨厌我对此答案投反对票;):

select c.ID, count(distinct o.OrdID) 
from client c, order o, status s
where c.ID = o.client_id(+)
and o.status_cd = s.status_cd 
and s.status_category='COMPL'
group by c.ID
;

要么

select c.ID
, nvl((select count(distinct o.OrdID) 
   from order o, status s 
   where c.ID = o.client_id 
     and o.status_cd = s.status_cd 
     and s.status_category='COMPL'
   ), 0) as order_count
from client c
group by c.ID
;

要么

with ord as
(select client_id, count(distinct o.OrdID) cnt
   from order o, status s 
   where 1=1
     and o.status_cd = s.status_cd 
     and s.status_category='COMPL'
   group by client_id
)
select c.ID
, nvl((select cnt from ord o where c.ID = o.client_id ), 0) as order_count
from client c
group by c.ID
;

要么

...

第二个WHERE应该是AND。

除此之外,在第二个连接条件下,还需要加号(+)标记左外部连接。 左外联接前两个表是不够的。

就像是

select c.ID, count(distinct o.OrdID) 
from client c, order o, status s
where c.ID=o.client_id(+)
and o.status_cd=s.status_cd(+)    AND   s.status_category='COMPL'
--                         ^^^    ^^^  (not WHERE)
group by c.ID

当然,如果使用正确的(SQL标准)联接语法,那就更好了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM