oracle sql left join and count,sum,group by

时间:2015-01-12 20:44:27

标签: sql oracle left-join

我想计算限制在给定资助者和会计年度的每个问题的项目数量,金额和百分比。出于某种原因,当我运行下面的查询时,我没有看到null 来自左连接的值。

项目和问题之间的关系是一个问题可以有很多项目。问题表由目标表链接。

已更新

select 
   q.sp_question_id,
   count(p.project_id) as projectCount,
   sum(p.funding) as amount,
   round(sum(p.funding)/sum(sum(p.funding)) over() *100) as percentTotal 
from questions q 
   left join projects p on p.fiscal_year = q.fiscal_year  
   join objectives o on o.sp_objective_id = p.sp_objective_id 
     and o.sp_question_id = q.sp_question_id 
     and o.fiscal_year = p.fiscal_year 
     and o.fiscal_year = 2014  
   join funders f on p.funder_id = f.funder_id 
where f.funder_short_name ='foo' 
   and q.fiscal_year = 2014  
group by q.sp_question_id 
order by q.sp_question_id;

 questionId   projectCount  amount          percentTotal
 q1           14            54510           4
 q2           29            1083598.72      76
 q3           1             19900           1
 q4           5             145631          10
 q5           1             124999          9
 q6           1             0               0 

预期结果

 questionId   projectCount  amount          percentTotal
 q1           14            54510           4
 q2           29            1083598.72      76
 q3           1             19900           1
 q4           5             145631          10
 q5           1             124999          9
 q6           1             0               0
 q7       <null>            <null>          <null>

使用左连接查询

select 
       q.sp_question_id,
       count(p.project_id) as projectCount,
       sum(p.funding) as amount,
       round(sum(p.funding)/sum(sum(p.funding)) over() *100) as percentTotal 
    from questions q 
       left join projects p on p.fiscal_year = q.fiscal_year  
       left join objectives o on o.sp_objective_id = p.sp_objective_id 
         and o.sp_question_id = q.sp_question_id 
         and o.fiscal_year = p.fiscal_year 
         and o.fiscal_year = 2014  
       left join funders f on p.funder_id = f.funder_id 
    where f.funder_short_name ='foo' 
       and q.fiscal_year = 2014  
    group by q.sp_question_id 
    order by q.sp_question_id;

结果

 questionId   projectCount  amount          percentTotal
 na           51            1428638.72      11
 q1           51            1428638.72      11
 q2           51            1428638.72      11
 q3           51            1428638.72      11
 q4           51            1428638.72      11
 q5           51            1428638.72      11
 q6           51            1428638.72      11
 q7           51            1428638.72      11
 qother       51            1428638.72      11

查询左边连接一直向下,其中子句调整

select 
   q.sp_question_id,
   count(p.project_id) as projectCount,
   sum(p.funding) as amount,
   round(sum(p.funding)/sum(sum(p.funding)) over() *100) as percentTotal 
from questions q 
   left join projects p on p.fiscal_year = q.fiscal_year 
   left join objectives o on o.sp_objective_id = p.sp_objective_id 
     and o.sp_question_id = q.sp_question_id 
     and o.fiscal_year = p.fiscal_year and o.fiscal_year = 2014 
   left join funders f on p.funder_id = f.funder_id and f.funder_short_name ='foo' 
   where q.fiscal_year = 2014 
group by q.sp_question_id 
order by q.sp_question_id;

结果

 questionId   projectCount  amount          percentTotal
 na           1225          299628985.01    11
 q1           1225          299628985.01    11
 q2           1225          299628985.01    11
 q3           1225          299628985.01    11
 q4           1225          299628985.01    11
 q5           1225          299628985.01    11
 q6           1225          299628985.01    11
 q7           1225          299628985.01    11
 qother       1225          299628985.01    11

2 个答案:

答案 0 :(得分:6)

你遇到的问题与sql最未知的问题之一有关:关系的传递性。

您正在项目和问题之间进行可选(外部)联接,但您要求项目和目标(以及资助者)之间的强制(内部联接)关系:

计算中间结果集的及物性系统给出了内连接的普遍性,因此基本上意味着忽略了中间的外连接。确切地说,它不会被忽略,但它会变成内部连接。

你得到的是内部连接一直向下的结果,而你实际上期望左连接表现为原样,并返回与任何项目无关的问题的空行......但是如上所述,引擎不能像这样工作。

在我的脑海中,我只是认为你可以一直使用左连接。但是,您可能会遇到比预期更多的空行。这实际上取决于您对数据做了什么。

此外,您的查询中似乎有一个应该修改的广泛联接。请试试这个:

select 
   q.sp_question_id,
   count(p.project_id) as projectCount,
   sum(p.funding) as amount,
   round(sum(p.funding)/sum(sum(p.funding)) over() *100) as percentTotal 
from questions q 
   left join objectives o on 
         o.sp_question_id = q.sp_question_id 
     and o.fiscal_year = 2014 
   left join projects p on o.fiscal_year = p.fiscal_year and o.sp_objective_id = p.sp_objective_id 
   left join funders f on p.funder_id = f.funder_id and f.funder_short_name ='foo' 
where q.fiscal_year = 2014 
group by q.sp_question_id 
order by q.sp_question_id;

答案 1 :(得分:0)

我最后通过左边连接两个子查询做了一些可怕的事情。如果有人有更好的方法,请发帖。

select t1.sp_question_id, t2.projectCount, t2.amount, t2.percentTotal   
from (select 
        q.sp_question_id 
      from questions q 
      where q.fiscal_year = 2014) t1

left join

(select 
   q.sp_question_id,
   count(p.project_id) as projectCount,
   sum(p.funding) as amount,
   round(sum(p.funding)/sum(sum(p.funding)) over() *100) as percentTotal 
from questions q 
   left join projects p on p.fiscal_year = q.fiscal_year  
   join objectives o on o.sp_objective_id = p.sp_objective_id 
     and o.sp_question_id = q.sp_question_id 
     and o.fiscal_year = p.fiscal_year 
   join funders f on p.funder_id = f.funder_id 
where f.funder_short_name ='foo' 
   and q.fiscal_year = 2014  
group by q.sp_question_id 
order by q.sp_question_id) t2
on t1.sp_question_id = t2.sp_question_id