mysql - 按多列和总和分组

时间:2012-09-11 07:41:04

标签: mysql join sum

我在查找以下mysql查询时遇到了一些麻烦。

这是一种跟踪用户具有特定费率的时间,具体取决于他们所执行的任务。我需要有一个摘要,所以我知道在本周末向用户支付的费用。

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

3 个答案:

答案 0 :(得分: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 :(得分: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


从这一点来总结数据很简单:)

答案 2 :(得分:0)

您的表格设计存在一些问题,即...如果您在“t&gt;类型”中添加了一行。那么你必须在你的“tUsers”中添加一列。表。这不是一个好的设计。

我略微修改了你的&#39; tUsers&#39;表并添加了另一个名为&#39; trates&#39;

的表

下面给出了新的tUses表结构

enter image description here

新的&#39; trates&#39;表就像

enter image description here

创建新曲目的脚本&#39;表格如下:

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;

将数据插入&#39; trates&#39;表格如下:

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

此设计的优点是,如果您在“t&gt;类型”中添加一种类型。那么你只需要在“trates”中插入一行&#39;表而不是在旧表中创建一列。

我使用了相同的&#39; tSession&#39;和&#t; t&#39;表..

创建新表后,您可以使用以下查询来获取所需的结果

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

对于Tom,

sessioncount是3,因为我为&#39; cleaning_30_min&#39;添加了单独的行。和&#39; cleaning_45_min&#39;在&#t; t&#39;表。我认为在这种情况下3是正确的会话数量