oracle sql left join 和 count, sum, group by

oracle sql left join and count, sum, group by

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

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

已更新

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

一直向下进行左连接查询并调整 where 子句

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

您遇到的问题与 sql 最不为人知的问题之一相关:关系的传递性。

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

计算中间结果集的传递系统使内连接占优势,这基本上意味着中间的外连接被忽略了。准确的说不是忽略,而是变成了inner join。

您得到的是内部联接一直向下的结果,而您实际上期望左联接按原样运行,并且 return 与任何项目无关的问题的空行。 ..但是引擎不是这样工作的,如上所述

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

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

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;

我最终通过左连接两个子查询做了如下可怕的事情。如果有人有更好的方法,请post。

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