SQL查询。需要GROUP BY两列中的值组合

时间:2013-02-12 14:15:30

标签: mysql sql group-by case

所以我有两张桌子。一个人拥有的股份数量:

Person_ID ||  Shares
1         ||  100
2         ||  150
3         ||  315
4         ||  75
5         ||  45
...

和另一个信息是否存在一个人(指定了两个列)以及他属于哪个组:

Person_id || barcode_presence || manual_presence || group_id
1         || NULL             || 1               || NULL
2         || 1                || NULL            || 1
3         || 1                || 0               || 2
4         || 0                || NULL            || 1
5         || 1                || 0               || 1
...

我需要找出所有存在的总和以及每个组中所有缺席共享的总和(NULL组也是一个组)。

我无法弄清楚的是,无论该人是否存在,都是通过两列(barcode_presence和manual_presence)的组合来计算出来的:

如果manual_presence = 1 - >本

否则if(manual_presence = NULL且barcode_presence = 1) - >本

其他一切都不存在。

这就是我到目前为止所得到的。

SELECT  presence_list.Person_id, presence_list.person_name, 
presence_list.barcode_presence, presence_list.manual_presence,
presence_list.group_id, people_data.Share 
, sum(people_data.Share)

FROM presence_list

INNER JOIN people_data
ON presence_list.Person_id = people_data.Person_ID

WHERE meeting_id = 1 AND voting_id = 0 
GROUP BY presence_list.group_id,  
barcode_presence,
manual_presence
ORDER BY presence_list.group_id
;

但很明显,这并没有给我预期的结果。它按group_id,barcode_presence和manual_presence的每种可能组合进行分组,如下所示:

Person_id || barcode_presence || manual_presence || group_id || share || sum(shares)
1         || NULL             || 1               || NULL     || 100   || 100
2         || 1                || NULL            || 1        || 150   || 150
4         || 0                || NULL            || 1        || 75    || 75
5         || 1                || 0               || 1        || 45    || 45
3         || 1                || 0               || 2        || 315   || 315

所以我正在寻找一种方法(在这种情况下)连接id为4和5的人,因为他们都不在,他们来自同一个群体,如下所示:

Person_id || barcode_presence || manual_presence || group_id || share || sum(shares)
1         || NULL             || 1               || NULL     || 100   || 100
2         || 1                || NULL            || 1        || 150   || 150
5         || 1                || 0               || 1        || 45    || **120**
3         || 1                || 0               || 2        || 315   || 315

我尝试过使用HAVING子句,但我没有办法处理像manual_presence = 1 OR (manual_presence is null AND barcode_presence = 1)这样的复杂表达式

任何想法或建议将不胜感激!先谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用case为在场和不在场的人群制作小组:

select  group_id
,       case 
        when barcode_presence = 1 and manual_presence = 1 then 1
        else 0
        end
,       sum(share)
from    presence_list pl
join    people_data pd
on      pl.person_id = pd.person_id
group by 
        group_id
,       case 
        when barcode_presence = 1 and manual_presence = 1 then 1
        else 0
        end
order by 
        group_id

答案 1 :(得分:1)

如果只能填充两列中的一列,请使用coalesce ...

 Group By group_id, Coalesce(barcode_presence, manual_presence)

如果没有,(可以,例如,barcode_presence = 1和presence = 0?),那么你需要决定你想要分组的值的哪些组合,并且只需要按表达式分组...绘制价值组合图表可能会有所帮助......

                barcode value     
 manual     Null      0        1
   Null     GrpA    GrpA     GrpB
     0      GrpC    GrpC     GrpB
     1      GrpB    GrpB     GrpB

说你想要将那些都是0和其他所有人分组,然后你会写...

 Group By group_id, case When isnull(barcode_presence, 0) = 0 
                          And isnull(manual_presence, 0) = 0 Then 0 Else 1 End

答案 2 :(得分:1)

如果我理解正确,我认为生成两列是可行的方法:

select pd.group_id,
       SUM(isPresent * pd.shares) as PresentShares,
       SUM((1 - isPresent)*pd.shares) as NotPresentShares
from (select pl.*,
             (case when manual_presence = 1 or 
                        manual_precence is null and barcode_presence = 1
                   then 1 else 0
              end) as IsPresent
           end
      from presence_list pl
     ) pl join
     people_data pd
     on pl.Person_id = pd.Person_ID
group by pd.group_id

子查询只是应用你的逻辑创建一个标志,当前为1,0表示不存在。方便的是,当以这种方式编码时,“1-IsPresent”为1表示不存在,0表示当前。

然后在聚合中使用此值来聚合共享。您可以将外部查询设为:

select group_id, IsPresent, sum(pd.shares)
from . . .
group by group_id, IsPresent

如果你真的想要在不同的行上使用这些值。