MySQL-将count函数的结果划分为从单独的列派生的列

时间:2019-03-15 15:54:38

标签: mysql count

我最近将其发布在Stack Exchange的另一页中,但我认为这是更合适的选择。

好吧,标题似乎有些令人困惑,但我一直在努力提出我需要此查询的内容,以便最好地对其进行解释。我的数据库中有3个表(使用MySQL Workbench),但是对于此查询,我只是尝试使用一个表。名为service_data的表具有以下列:

Services_ID|Service_Type|Day|Time|Customer_ID(FK)
1001       |SERVICE1    |Mon|0950|1    
1002       |SERVICE2    |Tue|1032|65
1003       |SERVICE3    |Wed|0859|4

该表包含大约200条记录,我的目标是将计时分组在一起,我通过这样做设法实现了这一目标:

select
case 
WHEN (Delivery_Time between '08:00:00' and '09:00:00') then '0800-0900'
WHEN (Delivery_Time between '09:00:00' and '10:00:00') then '0900-1000'
WHEN (Delivery_Time between '10:00:00' and '11:00:00') then '1000-1100'
WHEN (Delivery_Time between '11:00:00' and '12:00:00') then '1100-1200'
WHEN (Delivery_Time between '12:00:00' and '13:00:00') then '1200-1300'
WHEN (Delivery_Time between '13:00:00' and '14:00:00') then '1300-1400'
WHEN (Delivery_Time between '14:00:00' and '15:00:00') then '1400-1500'
WHEN (Delivery_Time between '15:00:00' and '16:00:00') then '1500-1600'
WHEN (Delivery_Time between '16:00:00' and '17:00:00') then '1600-1700'
WHEN (Delivery_Time between '17:00:00' and '18:00:00') then '1700-1800'
WHEN (Delivery_Time between '18:00:00' and '19:00:00') then '1800-1900'
WHEN (Delivery_Time between '19:00:00' and '20:00:00') then '1900-2000'
WHEN (Delivery_Time between '20:00:00' and '21:00:00') then '2000-2100'
      else 'Outside Opening Hours' 
  end as `Time Period`, 
   count(0) as 'count'
from service_data
group by `Time Period` 
order by count desc 
limit 20; 

哪个会产生以下结果:

TimePeriod  Count 
1700-1800   24
1500-1600   21
1200-1300   19
1400-1500   19
1800-1900   17
1100-1200   17
1300-1400   16
1600-1700   16
1000-1100   16
1900-2000   12
0800-0900   12
0900-1000   11

我现在想做的是将计数进行拆分,以便有4个列分别标记为SERVICE1 SERVICE2 SERVICE3和SERVICE4(Service_Type列中的值。希望这样看起来像这样:

TimePeriod|SERVICE1|SERVICE2|SERVICE3|SERVICE4
1700-1800 |   6    |   7    |    10  |   1
1500-1600 |   5    |   9    |    1   |   6
1200-1300 |   0    |   4    |    2   |   13`

这可能!!我敢肯定它一定是,但是我一直在努力解决,SQL不是我的母语!任何帮助将不胜感激

我的第二个问题是:

我希望第二个查询能够完成上述所有操作,然后将结果链接到一个主键customer_id是service_data中的外键的customer_data表,并将customer_id链接到象限(customer_data表中的列值NE,SE,SW,NW取决于坐标),并再次按象限和服务对计数进行分组,因此如下所示:

    TimePeriod| SERVICE1  | SERVICE2  | SERVICE3  | SERVICE4  |
   -----------|NE|SE|SW|NW|NE|SE|SW|NW|NE|SE|SW|NW|NE|SE|SW|NW|
    1700-1800 |2 |1 | 0| 3|4 | 0| 0|3 |2 |5 |2 |1 |0 |1 | 0| 0| 

再次有可能吗?或者我要求太多了吗?我想知道是否可以通过某种方式使用SUM(IF)函数来实现所有这些功能?

1 个答案:

答案 0 :(得分:0)

虽然我确实同意@Strawberry的观点,但是这确实需要一些入门知识。

这并没有针对性能或优雅进行任何优化,但如上所述,我已经使用您的数据对其进行了测试。

这是我的CREATE TABLE语句:

CREATE TABLE `service_data` (
  `services_id` int(11) NOT NULL,
  `service_type` varchar(45) DEFAULT NULL,
  `day` varchar(45) DEFAULT NULL,
  `time` time DEFAULT NULL,
  `customer_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`services_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

首先获取您的时间范围。我已将准时时间缩短了一秒钟,以免造成每小时上班时间的浪费。

create view spans as
  select time(concat(hour(time),':00:00')) as fromtime, 
         time(concat(hour(addtime(time,'00:59:59')),':00:00')) as totime
  from service_data

现在查找每行数据的时间范围。

create view withspans as
  select * from service_data s1
  join spans s2
    on time between fromtime and totime

现在汇总数据作为枢轴的输入。

create view summary as
  select fromtime, totime, service_type, count(*) as spancount
  from withspans
  group by fromtime, totime, service_type

现在通过派生表进行数据透视。

select w.fromtime, w.totime,
  s1.spancount as service1,
  s2.spancount as service2,
  s3.spancount as service3,
  s4.spancount as service4
  from summary w
  left join (select * from summary where service_type = 'SERVICE1') s1
    on s1.fromtime=w.fromtime and s1.totime=w.totime
  left join (select * from summary where service_type = 'SERVICE2') s2
    on s2.fromtime=w.fromtime and s2.totime=w.totime
  left join (select * from summary where service_type = 'SERVICE3') s3
    on s3.fromtime=w.fromtime and s3.totime=w.totime
  left join (select * from summary where service_type = 'SERVICE4') s4
    on s4.fromtime=w.fromtime and s4.totime=w.totime