使用GROUP BY和WITH ROLLUP删除冗余字段值

时间:2015-12-23 02:29:24

标签: mysql group-by rollup

我有4个Tables设置,我必须使用GROUP BY方法:

'超时'表

ot_id | user_id |       datefrom      |       dateto        
------+---------+---------------------+---------------------
  1   |     3   | 2015-12-21 17:00:00 | 2015-12-21 19:30:00 
------+---------+---------------------+---------------------
  9   |     1   | 2015-12-21 17:00:00 | 2015-12-21 19:00:00 
------+---------+---------------------+---------------------
  10  |     1   | 2015-12-21 17:00:00 | 2015-12-28 18:00:00 
------+---------+---------------------+---------------------
  11  |    45   | 2015-12-21 17:00:00 | 2015-12-21 19:00:00
------+---------+---------------------+---------------------
  12  |    45   | 2015-12-22 17:00:00 | 2015-12-22 18:30:00
------+---------+---------------------+---------------------
  13  |     4   | 2015-12-21 17:00:00 | 2015-12-21 19:00:00
------+---------+---------------------+---------------------
  14  |     4   | 2015-12-21 17:00:00 | 2015-12-21 18:00:00
------+---------+---------------------+---------------------
  15  |     1   | 2015-12-22 04:00:00 | 2015-12-22 08:00:00
------+---------+---------------------+---------------------
  16  |    55   | 2015-12-23 17:00:00 | 2015-12-23 19:00:00
------+---------+---------------------+---------------------
  17  |    56   | 2015-12-23 17:00:00 | 2015-12-23 19:00:00
------+---------+---------------------+---------------------
  18  |    56   | 2015-12-24 17:00:00 | 2015-12-24 18:30:00

'用户'表

user_id | dept_id | loc_id
--------+---------+---------
    1   |    2    |   58
--------+---------+---------
    3   |    2    |   58
--------+---------+---------
    4   |    2    |   58
--------+---------+---------
    45  |    2    |   58
--------+---------+---------
    55  |    1    |   58
--------+---------+---------
    56  |    1    |   47

'位置'表

loc_id | location
-------+----------------
   47  | DAGUPAN
-------+----------------
   58  | ADMINISTRATION

'部门'表

dept_id | department_name
--------+-----------------
    1   | ACCOUNTING
--------+-----------------
    2   | MIS

我的查询:

SELECT l.location, d.department_name,
        COALESCE(l.loc_id,'TOTAL') as loc_id,

((LEFT(SEC_TO_TIME(SUM(TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(dateto, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')) - TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(datefrom, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')))), 2) * 60)

+

SUBSTRING(SEC_TO_TIME(SUM(TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(dateto, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')) - TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(datefrom, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')))), 4, 2)) / 60

AS totalHrs


FROM `overtime` AS o
INNER JOIN `users` AS u ON o.user_id=u.user_id
INNER JOIN `location` AS l ON u.loc_id=l.loc_id
INNER JOIN `department` AS d ON u.dept_id=d.dept_id

GROUP BY l.loc_id, d.dept_id WITH ROLLUP

给我这个:

enter image description here

我想要的是这样的:

|----------------|-----------------|-----------------|--------------------------|
|--- location ---|--- department---|--- totalHrs ----|--- over all totalHrs ----|
|----------------|-----------------|-----------------|--------------------------|
|     DAGUPAN    |   ACCOUNTING    |       3.5       |                          |
|----------------|-----------------|-----------------|--------------------------|
|      (NULL)    |     (NULL)      |       TOTAL     |            3.5           |
|----------------|-----------------|-----------------|--------------------------|
| ADMINISTRATION |   ACCOUNTING    |        2        |                          |
|----------------|-----------------|-----------------|--------------------------|
|      (NULL)    |      MIS        |        16       |                          |
|----------------|-----------------|-----------------|--------------------------|
|      (NULL)    |      (NULL)     |       TOTAL     |             18           |
|----------------|-----------------|-----------------|--------------------------|

是否可以删除location字段的冗余循环? 另外,我想创建一个名为column的新over all totalHrs并使用WITH ROLLUP获取总值

提前致谢!

  

EDITED

找到了这个SQL Fiddle,它只是一个不同的表格结构。但这正是我想要的。

1 个答案:

答案 0 :(得分:1)

不确定您将在何处使用此功能。所以我假设您使用编程环境创建某种报告。进一步阅读为什么这很重要。

  1. 从您的查询中删除loc_id似乎不会影响它,那么为什么要在需要时保留它呢?
  2. 删除汇总

    SELECT l.location, d.department_name,
    ((LEFT(SEC_TO_TIME(SUM(TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(dateto, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')) - TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(datefrom, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')))), 2) * 60)
    +
    SUBSTRING(SEC_TO_TIME(SUM(TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(dateto, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')) - TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(datefrom, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')))), 4, 2)) / 60
    AS totalHrs
    FROM `overtime` AS o
    INNER JOIN `users` AS u ON o.user_id=u.user_id
    INNER JOIN `location` AS l ON u.loc_id=l.loc_id
    INNER JOIN `department` AS d ON u.dept_id=d.dept_id
    GROUP BY l.loc_id, d.dept_id
    
  3. 使用我使用的数据生成(与您的数据不同):

    location    department_name totalHrs
    Dagupan accounting  7
    administration  accounting  2.5
    administration  mis 5
    administration  bod 5.5
    

    因此,您想要的汇总将在每次更改位置时添加行(在总小时行中将它们相加。

    给你以下内容:

    location    department_name totalHrs
    Dagupan accounting  7
    Dagupan accounting  7
    administration  accounting  2.5
    administration  mis 5
    administration  bod 5.5
    administration  bod 13
    administration  bod 20 -----This row is the total of the extra rows added 7 and 13
    

    如果您不希望将其作为输出,则可以始终省略with rollup选项并使用编程技术显示此查询生成的行,并将它们汇总在一个单独的变量中以便稍后显示。

    这是我过去常常测试的sqlfiddle

    如果您可以添加获得输出所需的重要字段和数据,如果您不使用编程环境,我可以更进一步。

    更新后我创建了这个:

        select case when rownum = 1 then location else null end location,
    case when rownum = 1 then department_name else 'total' end department_name,totalHrs
    from
    (select *,
    @row:=(case when @prev=loc_id and @predept=dept_id 
               then @row else 0 end) + 1 as rownum,
        @prev:=loc_id ploc_id,
        @predept:=dept_id pdept_id
    from
    (
    SELECT l.location, d.department_name,
    ((LEFT(SEC_TO_TIME(SUM(TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(dateto, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')) - TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(datefrom, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')))), 2) * 60)
    +
    SUBSTRING(SEC_TO_TIME(SUM(TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(dateto, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')) - TIME_TO_SEC(DATE_FORMAT(STR_TO_DATE(datefrom, '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s')))), 4, 2)) / 60
    AS totalHrs,u.dept_id,u.loc_id
    FROM `overtime` AS o
    INNER JOIN `users` AS u ON o.user_id=u.user_id
    INNER JOIN `location` AS l ON u.loc_id=l.loc_id
    INNER JOIN `department` AS d ON u.dept_id=d.dept_id
    GROUP BY l.loc_id, d.dept_id with rollup ) src) src2
    

    new fiddle

    为您多加一点:

    替换

    case when rownum = 1 then department_name else 'total' end department_name,
    

    case when rownum = 1 then department_name else concat(location,' total') end department_name,