2013-02-12 182 views
1

所以我有兩個表。一個與人們有股量:SQL查詢。需要GROUP BY兩列值的組合

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 
... 

我需要找出每一組中所有缺席股票的總和和總和(空值組也是一個組)。

我不能找出的事情是,該人是否存在或不存在是由兩列(barcode_presence和manual_presence)的組合計算出:

如果manual_presence = 1 - >本

else if(manual_presence = NULL and 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)

任何意見或建議將是複雜的表達式欣賞d!事先感謝!

+0

您正在使用哪些DBMS?甲骨文? Postgres的? – 2013-02-12 14:17:20

+0

我正在使用MySQL。 – Egor 2013-02-12 14:20:50

回答

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 
+0

這是一個很好的解決方案,謝謝!我結束了使用另一個,但儘管如此,這是非常有益的! – Egor 2013-02-12 15:18:54

1

如果只有兩列的人可以永遠被填充,使用合併...

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 
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 

如果你真的想在不同的行上的值。

+0

偉大的解決方案!這正是我所需要的,但是,我遇到了一個問題,我對此感到困惑不解。那就是腳本輸出的內容。
Group_id || PresentShares || NotPresentShares
|| 3380 \t || 10140
但是,我知道一個事實,即第5組中只有2個人,而且他們每個人的確有3380個份額。 任何想法爲什麼它計數NotPresentShares 3次? – Egor 2013-02-12 15:24:07