2012-09-11 563 views
2

我在計算以下mysql查詢時遇到了一些麻煩。mysql-group by multiple columns and sum

這意味着一種時間跟蹤,用戶根據他們所做的任務具有一定的費率。我需要有一個總結,所以我知道在本週結束時要向用戶付款。

-----------tSessions--------------------------- 
|id  |userid |typeid |session_length_min 
----------------------------------------------- 
|1  |1  |1  |30 
----------------------------------------------- 
|2  |1  |1  |45 
----------------------------------------------- 
|3  |1  |2  |(null) 
----------------------------------------------- 
|4  |2  |2  |(null) 
----------------------------------------------- 


-----------tUsers----------------------------------------------------------------------------------- 
|id  |name |rate_cleaning_30_min |rate_cleaning_45_min |rate_kitchenwork |rate_dogwalking 
---------------------------------------------------------------------------------------------------- 
|1  |Tom |30      |50      |40    |20 
---------------------------------------------------------------------------------------------------- 
|2  |Joe |35      |60      |45    |20 
---------------------------------------------------------------------------------------------------- 
|3  |Dave |40      |60      |30    |10 
---------------------------------------------------------------------------------------------------- 


-----------tTypes---------------- 
|id  |name 
--------------------------------- 
|1  |Cleaning 
--------------------------------- 
|2  |Kitchenwork 
--------------------------------- 
|3  |Dogwalking 
--------------------------------- 


============== Required Result ==================== 
|username |sessioncount |amount_to_pay 
--------------------------------------------------- 
|Tom  |2    |120 
--------------------------------------------------- 
|Joe  |1    |45 
--------------------------------------------------- 

下面的查詢是一個,如果我不那麼成功的方法:

SELECT 
tSessions.id, 
tSessions.userid, 
tSessions.typeid, 
tSessions.session_length_min, 
SUM(tUsers.rate_cleaning_30_min) AS rate_cleaning_30_min_sum, 
SUM(tUsers.rate_cleaning_45_min) AS rate_cleaning_45_min_sum, 
SUM(tUsers.rate_kitchenwork) AS rate_kitchenwork, 
SUM(tUsers.rate_dogwalking) AS rate_dogwalking, 
Count(*) AS sessioncount, 
FROM 
tSessions 
INNER JOIN tUsers ON tSessions.userid = tUsers.id 
WHERE WEEKOFYEAR(FROM_UNIXTIME(datetime))=WEEKOFYEAR(NOW())-1 
GROUP BY 
tSessions.userid, 
tSessions.typeid 
+0

我試過類似的東西,但沒有取得太大的成功: – Phil

+0

問題到底在哪裏?預期產出是多少? – fancyPants

+0

我不知道如何去「需要的結果」 – Phil

回答

2

這裏是一個SQLFiddle example

select tUsers.Name, 
count(*) as sessioncount, 
sum(
if(typeid=1, 
      if(session_length_min<=30,rate_cleaning_30_min, 
      rate_cleaning_45_min) 
      ,0) 
+ 
    if(typeid=2,rate_kitchenwork,0) 
+ 
if(typeid=3,rate_dogwalking,0) 
) as amount_to_pay 

from 
tSessions 
left join tUsers on tSessions.userid=tUsers.id 
group by tUsers.Name 

但是你的基本方案是不好的。如果您需要添加或刪除任務類型會怎麼樣。你應該分開tUsers和任務的價格。只需添加新表tRates和修改tTypes:

-----------tTypes---------------- 
    |id  |name 
    --------------------------------- 
    |1  |Cleaning 30 min 
    --------------------------------- 
    |2  |Kitchenwork 
    --------------------------------- 
    |3  |Dogwalking 
    --------------------------------- 
    |4  |Cleaning 45 min 
    --------------------------------- 

-----------tSessions-------- 
|id  |userid |typeid | 
---------------------------- 
|1  |1  |1  | 
---------------------------- 
|2  |1  |4  | 
---------------------------- 
|3  |1  |2  | 
---------------------------- 
|4  |2  |2  | 
---------------------------- 


-----------tUsers----------------- 
|id  |name | 
----------------- 
|1  |Tom | 
----------------- 
|2  |Joe | 
----------------- 
|3  |Dave | 
----------------- 


and add tRates table with USER<->TASKS rates: 


-----------tRates-------- 
|id  |userid |typeid | rate | 
--------------------------------------- 
|1  |1  |1  |30  | 
-------------------------------------- 
|2  |1  |2  |40  | 
-------------------------------------- 
|3  |1  |3  |20  | 
-------------------------------------- 
|4  |1  |4  |50  | 
-------------------------------------- 
|5  |2  |1  |35  | 
-------------------------------------- 
|6  |2  |2  |45  | 
-------------------------------------- 
|7  |2  |3  |20  | 
-------------------------------------- 
|8  |2  |4  |60  | 
-------------------------------------- 
|9  |3  |1  |40  | 
-------------------------------------- 
|10  |3  |2  |30  | 
-------------------------------------- 
|11  |3  |3  |10  | 
-------------------------------------- 
|12  |3  |4  |60  | 
-------------------------------------- 
1


我相信這裏的問題是,你的數據不正確寫入。
首先,你需要一個價格表:

 
CREATE TABLE `trates` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(11) NOT NULL, 
    `type_id` int(11) NOT NULL, 
    `rate` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `unique` (`user_id`,`type_id`) 
)

填充表,每個人的正確率:

 
INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Tom'),(SELECT id FROM ttypes WHERE NAME = 'Cleaning'),30); 
INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Tom'),(SELECT id FROM ttypes WHERE NAME = 'Kitchenwork'),40); 
INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Tom'),(SELECT id FROM ttypes WHERE NAME = 'Dogwalking'),20); 

INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Joe'),(SELECT id FROM ttypes WHERE NAME = 'Cleaning'),35); 
INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Joe'),(SELECT id FROM ttypes WHERE NAME = 'Kitchenwork'),45); 
INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Joe'),(SELECT id FROM ttypes WHERE NAME = 'Dogwalking'),20); 

INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Dave'),(SELECT id FROM ttypes WHERE NAME = 'Cleaning'),40); 
INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Dave'),(SELECT id FROM ttypes WHERE NAME = 'Kitchenwork'),30); 
INSERT INTO trates VALUES (NULL,(SELECT id FROM tusers WHERE NAME = 'Dave'),(SELECT id FROM ttypes WHERE NAME = 'Dogwalking'),10); 


接下來,還有一個問題與費率類型在這裏,因爲你指的是2組合的數據 - 工作類型+工作時間
清潔30分鐘
清潔45分鐘
這是否意味着清潔只能在這兩個方面完成?
其他任務可以是30和45分鐘嗎?
價格通常是每小時,這意味着如果一個速度爲每小時$ 20一個人工作120分鐘它應該是TimeSpent/60 * PayPerHourRate(120/60 * 20)

如果它總是30到45分鐘,我會建議一個值添加到您的類型表:

id name 
1 Cleaning30m 
2 Kitchenwork 
3 Dogwalking 
4 Cleaning45m


從這個角度總結的數據很容易:)

0

。在你的表的設計,即一些問題...如果你在'tTypes'表中添加一行,那麼你必須在你的'tUsers'表中添加一列。這不是一個好設計。

我稍加修改你的「tUsers」表並添加了一個名爲下面

enter image description here

新的「trates」表「trates」

新tUses表結構是多一個表會像

enter image description here

腳本來創建新的 'trates' 下面的表格中給出

CREATE TABLE `trates` (
    `id` INT(10) NOT NULL AUTO_INCREMENT, 
    `typeid` INT(11) NOT NULL DEFAULT '0', 
    `userid` INT(11) NOT NULL DEFAULT '0', 
    `rate` INT(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id`) 
) 
COLLATE='latin1_swedish_ci' 
ENGINE=InnoDB 
AUTO_INCREMENT=13; 

腳本,將您的數據低於

INSERT INTO `trates` (`id`, `typeid`, `userid`, `rate`) VALUES 
    (1, 1, 1, 30), 
    (2, 2, 1, 50), 
    (3, 3, 1, 40), 
    (4, 4, 1, 20), 
    (5, 1, 2, 35), 
    (6, 2, 2, 60), 
    (7, 3, 2, 45), 
    (8, 4, 2, 20), 
    (9, 1, 3, 40), 
    (10, 2, 3, 60), 
    (11, 3, 3, 30), 
    (12, 3, 3, 10); 

利用這一設計的「trates」表中給出的,如果你添加更多的類型「tTypes」表,那麼你只需要插入'Trates'表中的一行而不是在您舊錶中創建一列。

我用同樣的 'tSessions' 和 'tTypes' 表..

創建我的新表後,可以使用以下查詢來獲取所需的結果

select usr.name, (select count(distinct userid,typeid) 
from tsessions tsess where 
tsess.userid=usr.id) as 'sessioncount', sum(rate) as 'amount_to_pay' 
from tusers usr,trates rts,tsessions sess1 where rts.userid=usr.id 
    and rts.typeid=sess1.typeid and sess1.userid=usr.id 
group by usr.name 

enter image description here

sessioncount是3,因爲我在'tTypes'表中爲'cleaning_30_min'和'cleaning_45_min'添加了單獨的行。我認爲3是正確的sessioncount在這種情況下