2012-09-11 333 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在这种情况下