简体   繁体   English

oracle sql左联接和计数,求和,分组

[英]oracle sql left join and count, sum, group by

i want to calculate the project count, amount, and percent total for each question restricted to a given funder and fiscal year. 我想计算每个问题的项目数,金额和总计百分比,这些问题仅限于给定的资助者和财政年度。 for some reason when i run the query below, i'm not seeing the null values from the left join. 由于某些原因,当我运行下面的查询时,我没有从左联接中看到空值。

the relationship between projects and questions is that a question can have many projects. 项目和问题之间的关系是一个问题可以有多个项目。 the questions table is linked by the objectives table. 问题表由目标表链接。

UPDATED 更新

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 

expected result 预期结果

 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>

query with left joins all the way down 带有左连接的查询一直向下

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;

result 结果

 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

query with left joins all the way down and where clauses adjusted 带有左连接的查询一直向下进行,其中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;

result 结果

 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

The problem you're having relates to one of the most unknown problems of sql: the transitivity of relationships. 您遇到的问题与sql的最未知问题之一有关:关系的可传递性。

You're doing an optional (outer) join between projects and questions, but you're asking for a mandatory (inner join) relationship between projects and objectives (and funders): 您正在进行项目和问题之间的可选(外部)联接,但是您正在寻求项目和目标(以及出资者)之间的强制性(内部联接)关系:

The transitivity system which calculates the intermediary resultsets gives prevalence to the inner join, which as a result basically means the outer join in the middle is ignored. 计算中间结果集的可及性系统普遍使用内部联接,因此基本上意味着中间的外部联接被忽略。 To be exact, it is not ignored, but it becomes an inner join instead. 确切地说,它不会被忽略,但是它将变成一个内部联接。

What you get is the result of an inner join all the way down, while you're actually expecting the left join to behave as is and return null rows for the questions not related to any projects... But the engine does not work like this, as described above. 您得到的是内部连接一直向下的结果,而您实际上希望左连接按原样运行,并为与任何项目无关的问题返回空行...但是引擎无法像如上所述。

Out of my head, I just think you could use left joins all the way down. 我不由自主地想到,您可以一直使用左连接。 But then you probably would face more null rows than you expect. 但是,那么您可能会遇到比预期更多的空行。 It really depends what you're doing with the data. 这实际上取决于您对数据的处理方式。

Also, it seems there's a broad join in your query that should be modified. 另外,似乎您的查询中存在广泛的联接,应该对其进行修改。 Please try this: 请尝试以下方法:

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;

i ended up doing something ghastly like below by left joining two subqueries. 我最后通过加入两个子查询来做下面的可怕的事情。 if someone has a better way of doing this, please 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 

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

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