在MySQL中体验竖表转横表以及几个关键字使用

场景:在MySQL中体验竖表转横表以及几个关键字使用
版本:mysql-5.7.33-winx64
记录:NO.247
在工厂中有这样一个场景,24小时监测设备A的温度。在设备A中安装温度传感器B采样温度,每个整点小时段内至少采集一次,并把数据上传到上位机。每天需至少有24个点,且分布在各个小时段之内。第一个点使用0标记。在整点时间段内温度传感器可以多次采集并上传数据。比如在时间T采集温度,T满足0:00:00 ≤T<0:00:59,则标记为0点,在T满足1:00:00 ≤T<0:00:59则标记为1点,依次类推。具体见表格。
        
温度传感器B采集设备A温度并上传到上位机,上位机C接收到每个点数据直接以(Key,Value)方式组织数据写入Redis列队D,后台微服务E扫描Redis队列,取出数据写入MySQL数据库F中。
整点温度数据-竖表:t_sensor_data_vertical持久化存储。表结构如下:

CREATE TABLE t_sensor_data_vertical (
  ID BIGINT(18) NOT NULL COMMENT '标识',
  GATHER_DATE DATE NOT NULL COMMENT '数据采集日期,yyyymmdd',
  POSITION_DIR INT(6) NOT NULL COMMENT '位置温度(0:东,2:西,3:南,4:北)',
  MARK_POINT_NUM INT(6) DEFAULT NULL COMMENT '传感器需采集点数',
  MARK_GATHER_TIME INT(6) NOT NULL COMMENT '标识时间点: 在0点的数据标识为0,在1点的数据标识为1,以此类推,23点采集点为23',
  T DECIMAL(6,2) DEFAULT NULL COMMENT '温度',
  DATA_FROM VARCHAR(10) CHARACTER SET utf8 DEFAULT '1' COMMENT '1:设备自动采集的温度,2:人工手动写入温度',
  GATHER_TIME DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '写入时间'
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='整点温度数据-竖表';

类似这样的表我们叫做竖表,也叫作纵表,表结构为:主键、字段代码、字段值。
传感器B采集一天24个点数据(每小时只采集一个点)如下:
        
从上图看,传感器B的ID=202105010001,每个小时段只采集一条数据则24小时内有24个点,如果每个小时段采集2个点就有48个点,以此类推。这样在很多场景查询此表使用不方便,那么就可以将竖表24个点根据业务规则转换为横表,传感器B的ID=202105010001,在一天24个点,就只需一条数据。
横表,表结构为:主键、字段1、字段2、字段3...。整点温度数据-横表t_sensor_data_hrizontal,如下:

CREATE TABLE t_sensor_data_hrizontal (
  ID BIGINT(18) NOT NULL COMMENT '标识',
  GATHER_DATE DATE NOT NULL COMMENT '数据采集日期,yyyymmdd',
  POSITION_DIR INT(6) NOT NULL COMMENT '位置温度(0:东,2:西,3:南,4:北)',
  MARK_DATA_WHOLE VARCHAR(128) CHARACTER SET utf8 DEFAULT NULL COMMENT '标记数据完整,某个点有数据则为1,无数据则为0',
  MARK_POINT_NUM INT(6) DEFAULT NULL COMMENT '传感器需采集点数',
  T1 DECIMAL(6,2) DEFAULT NULL COMMENT '0点温度',
  T2 DECIMAL(6,2) DEFAULT NULL COMMENT '1点温度',
  T3 DECIMAL(6,2) DEFAULT NULL COMMENT '2点温度',
  T4 DECIMAL(6,2) DEFAULT NULL COMMENT '3点温度',
  T5 DECIMAL(6,2) DEFAULT NULL COMMENT '4点温度',
  T6 DECIMAL(6,2) DEFAULT NULL COMMENT '5点温度',
  T7 DECIMAL(6,2) DEFAULT NULL COMMENT '6点温度',
  T8 DECIMAL(6,2) DEFAULT NULL COMMENT '7点温度',
  T9 DECIMAL(6,2) DEFAULT NULL COMMENT '8点温度',
  T10 DECIMAL(6,2) DEFAULT NULL COMMENT '9点温度',
  T11 DECIMAL(6,2) DEFAULT NULL COMMENT '10点温度',
  T12 DECIMAL(6,2) DEFAULT NULL COMMENT '11点温度',
  T13 DECIMAL(6,2) DEFAULT NULL COMMENT '12点温度',
  T14 DECIMAL(6,2) DEFAULT NULL COMMENT '13点温度',
  T15 DECIMAL(6,2) DEFAULT NULL COMMENT '14点温度',
  T16 DECIMAL(6,2) DEFAULT NULL COMMENT '15点温度',
  T17 DECIMAL(6,2) DEFAULT NULL COMMENT '16点温度',
  T18 DECIMAL(6,2) DEFAULT NULL COMMENT '17点温度',
  T19 DECIMAL(6,2) DEFAULT NULL COMMENT '18点温度',
  T20 DECIMAL(6,2) DEFAULT NULL COMMENT '19点温度',
  T21 DECIMAL(6,2) DEFAULT NULL COMMENT '20点温度',
  T22 DECIMAL(6,2) DEFAULT NULL COMMENT '21点温度',
  T23 DECIMAL(6,2) DEFAULT NULL COMMENT '22点温度',
  T24 DECIMAL(6,2) DEFAULT NULL COMMENT '23点温度',
  DATA_FROM VARCHAR(10) CHARACTER SET utf8 DEFAULT '0' COMMENT '0:设备自动采集的温度,1:人工手动写入温度',
  GATHER_TIME DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '写入时间',
  PRIMARY KEY (ID,GATHER_DATE,POSITION_DIR)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='整点温度数据-横表';

其中,ID,GATHER_DATE,POSITION_DIR,作为t_sensor_data_hrizontal表主键。
在一行中存储部分截图如:

竖表转换为横表sql如下:

INSERT INTO t_sensor_data_hrizontal
select 
  ID,GATHER_DATE,POSITION_DIR,
  CONCAT(CASE WHEN T1 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T1 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T2 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T3 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T4 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T5 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T6 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T7 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T8 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T9 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T10 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T11 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T12 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T13 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T14 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T15 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T16 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T17 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T18 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T19 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T20 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T21 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T22 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T23 IS NOT NULL THEN '1' ELSE '0'END,
  CASE WHEN T24 IS NOT NULL THEN '1' ELSE '0'END
  )AS MARK_DATA_WHOLE,MARK_POINT_NUM,
  T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,
  DATA_FROM,now() as GATHER_TIME
from (
SELECT
  AA.ID AS ID,AA.GATHER_DATE AS GATHER_DATE,AA.POSITION_DIR AS POSITION_DIR,
 (CASE WHEN MIN(AA.MARK_POINT_NUM) IS NOT NULL THEN MIN(AA.MARK_POINT_NUM) ELSE 24 END) AS MARK_POINT_NUM,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '0' THEN AA.T ELSE NULL END) AS T1,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '1' THEN AA.T ELSE NULL END) AS T2,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '2' THEN AA.T ELSE NULL END) AS T3,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '3' THEN AA.T ELSE NULL END) AS T4,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '4' THEN AA.T ELSE NULL END) AS T5,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '5' THEN AA.T ELSE NULL END) AS T6,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '6' THEN AA.T ELSE NULL END) AS T7,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '7' THEN AA.T ELSE NULL END) AS T8,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '8' THEN AA.T ELSE NULL END) AS T9,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '9' THEN AA.T ELSE NULL END) AS T10,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '10' THEN AA.T ELSE NULL END) AS T11,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '11' THEN AA.T ELSE NULL END) AS T12,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '12' THEN AA.T ELSE NULL END) AS T13,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '13' THEN AA.T ELSE NULL END) AS T14,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '14' THEN AA.T ELSE NULL END) AS T15,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '15' THEN AA.T ELSE NULL END) AS T16,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '16' THEN AA.T ELSE NULL END) AS T17,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '17' THEN AA.T ELSE NULL END) AS T18,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '18' THEN AA.T ELSE NULL END) AS T19,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '19' THEN AA.T ELSE NULL END) AS T20,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '20' THEN AA.T ELSE NULL END) AS T21,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '21' THEN AA.T ELSE NULL END) AS T22,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '22' THEN AA.T ELSE NULL END) AS T23,
  MAX(CASE WHEN AA.MARK_GATHER_TIME = '23' THEN AA.T ELSE NULL END) AS T24,
  SUM(case when AA.DATA_FROM IS NOT NULL THEN 0 ELSE 1 END)AS DATA_FROM
FROM
  t_sensor_data_vertical AA
WHERE AA.GATHER_DATE = '20210501'
GROUP BY AA.ID,AA.GATHER_DATE,AA.POSITION_DIR
) BB;

在竖表t_sensor_data_vertical造数据sql如下:

INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','0',10.5,'1','2021-05-01 00:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','1',11.5,'1','2021-05-01 01:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','2',12.5,'1','2021-05-01 02:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','3',13.5,'1','2021-05-01 03:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','4',14.5,'1','2021-05-01 04:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','5',15.5,'1','2021-05-01 05:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','6',16.5,'1','2021-05-01 06:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','7',17.5,'1','2021-05-01 07:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','8',18.5,'1','2021-05-01 08:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','9',19.5,'1','2021-05-01 09:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','10',20.5,'1','2021-05-01 10:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','11',21.5,'1','2021-05-01 11:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','12',22.5,'1','2021-05-01 12:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','13',23.5,'1','2021-05-01 13:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','14',24.5,'1','2021-05-01 14:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','15',25.5,'1','2021-05-01 15:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','16',26.5,'1','2021-05-01 16:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','17',27.5,'1','2021-05-01 17:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','18',28.5,'1','2021-05-01 18:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','19',30.5,'1','2021-05-01 19:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','20',31.5,'1','2021-05-01 20:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','21',32.5,'1','2021-05-01 21:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','22',33.5,'1','2021-05-01 22:01:06');
INSERT INTO t_sensor_data_vertical (ID,GATHER_DATE,POSITION_DIR,MARK_POINT_NUM,MARK_GATHER_TIME,T,DATA_FROM,GATHER_TIME)
VALUES (202105010001,'20210501','0','24','23',50.5,'1','2021-05-01 23:01:06');

本例MySQL环境是如下:
        
本例主要想体验一下如下函数和关键字使用。
CASE WHEN 条件 THEN 成立的结论 ELSE 不成立的结论 END ;
MAX(),取最大值;
GROUP BY,分组,除了分组字段,其它字段均需有类似MAX()、SUM()、COUNT()等函数辅助;
CONCAT(),连接多个字符串;
SUM(),求和;
子查询;
INSERT INTO 表 (字段) VALUES(值),插入语句;
PRIMARY KEY (ID,GATHER_DATE,POSITION_DIR),联合主键;
DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,字段自动更新当前时间。
以上,感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值