最近公司里做遇到了一点麻烦的事情,需要根据时间动态的查询每日每月的二维码扫描量以及优惠卷使用量。我想着,这不跟动态统计某时间内登陆次数之类的业务场景这种需求大致上是一样的吗,接下来我就用如标题所示的业务场景解决这个问题。
创建用户登录记录表,假定用户每登录一次向此表存入一条数据
CREATE TABLE `user_login_record` (
`id` VARCHAR(16) NOT NULL COMMENT '主键',
`user_id` VARCHAR(16) NOT NULL COMMENT '用户id',
`login_time` datetime NOT NULL COMMENT '登陆时间',
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
准备数据
INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1111','00001','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1112','00001','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1113','00001','2019-07-02 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1114','00001','2019-07-02 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1115','00001','2019-07-02 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1116','00001','2019-07-01 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1117','00001','2019-07-01 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1118','00001','2019-07-01 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1119','00001','2019-06-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1120','00001','2019-06-04 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1122','00001','2019-06-04 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1123','00001','2019-05-11 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1124','00001','2019-05-12 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1125','00001','2019-05-10 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1126','00001','2019-05-11 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1127','00001','2019-05-19 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1128','00001','2019-05-20 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1129','00001','2019-06-11 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1130','00001','2019-06-11 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1131','00001','2019-06-08 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1132','00001','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1133','00002','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1134','00002','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1135','00002','2019-06-13 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1136','00002','2019-06-12 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1137','00002','2019-06-11 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1138','00002','2019-06-08 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1139','00003','2019-06-10 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1140','00003','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1141','00003','2019-07-02 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1142','00003','2019-07-01 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1143','00003','2019-06-20 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1144','00003','2019-06-14 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1145','00003','2019-06-10 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1146','00003','2019-06-10 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1147','00004','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1148','00004','2019-07-02 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1149','00004','2019-07-01 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1150','00004','2019-06-11 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1151','00004','2019-06-18 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1152','00004','2019-06-13 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1153','00004','2019-06-15 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1154','00004','2019-07-02 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1155','00004','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1156','00004','2019-06-30 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1157','00004','2019-06-09 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1158','00004','2019-06-20 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1159','00004','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1160','00005','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1161','00005','2019-07-03 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1162','00005','2019-07-01 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1163','00005','2019-07-02 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1164','00005','2019-06-30 15:51:58');INSERT INTO `popuconsole`.`user_login_record`(`id`,`user_id`,`login_time`) VALUES ('1165','00005','2019-06-10 15:51:58');
问题:那怎么通过一个sql 查询出不同用户在不同时间内的登陆次数呢?
如果 group by 用户id,则时间作为了动态的列;如果group by 登陆时间,则用户id作为了动态的列,那么 怎么查询如下图所示的语句呢?
如果要我直接写sql语句的话 我会这么写
SELECT
user_id AS userId,
SUM( IF ( DATE_FORMAT( login_time, '%Y%m' ) = '201905', 1, 0 ) ) AS '201905',
SUM( IF ( DATE_FORMAT( login_time, '%Y%m' ) = '201906', 1, 0 ) ) AS '201906',
SUM( IF ( DATE_FORMAT( login_time, '%Y%m' ) = '201907', 1, 0 ) ) AS '201907'
FROM
user_login_record
GROUP BY
user_id
从上面的sql 上来看 这是一个静态的sql,那么 如何的确定有多少个月,每个月如何的显示呢?即,sum()是怎么得来的?
现在需要介绍两个mysql 函数
1、group_concat() :将group by产生的同一个分组中的值连接起来,返回一个字符串结果。
2、ONCAT(str1,str2,…) :返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。
SELECT
GROUP_CONCAT(
DISTINCT CONCAT( 'SUM(IF(DATE_FORMAT(login_time,''%Y%m'') = ''', DATE_FORMAT( c.login_time, '%Y%m' ), ''',1, 0)) AS ''', DATE_FORMAT( c.login_time, '%Y%m' ), '''' )
)
FROM
user_login_record c
WHERE
c.login_time
通过以上的sql可以得出 一系列sum()函数的字符串 。但是是没法通过一个sql查询出来的,以上的步骤 只等通过 查询出结果字符串 然后把结果字符串粘贴过去生成查询结果。
自然而然的 想到了存储 过程下面 我创建了一个不带条件的存储过程
CREATE DEFINER=`root`@`%` PROCEDURE `UserLoginTimesSatistics`()
BEGIN
SET @sql = NULL;
SELECT
GROUP_CONCAT(
DISTINCT CONCAT( 'SUM(IF(DATE_FORMAT(login_time,''%Y%m'') = ''', DATE_FORMAT( c.login_time, '%Y%m' ), ''',1, 0)) AS ''', DATE_FORMAT( c.login_time, '%Y%m' ), '''' )
)
FROM
user_login_record c
WHERE
c.login_time INTO @sql ;
SELECT CONCAT( 'SELECT user_id as userId , ', @sql, ' from user_login_record GROUP BY user_id' ) INTO @sql;
PREPARE stmt FROM @SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
保存成功之后 直接通过
call UserLoginTimesSatistics()
就可以得到上图所示结果 是不是很酷
自然而然的,动态的统计某时间内登陆的次数只需要将上述的存储过程改进一下就行了,我的改进如下
CREATE DEFINER=`root`@`%` PROCEDURE `UserLoginTimesSatistics`( IN beginTime VARCHAR(50),IN endTime VARCHAR(50) )
BEGIN
SET @sql = NULL;
if ( beginTime = '' || beginTime is NULL || endTime ='' || endTime is NULL) THEN
SELECT
GROUP_CONCAT(
DISTINCT CONCAT( 'SUM(IF(DATE_FORMAT(login_time,''%Y%m'') = ''', DATE_FORMAT( c.login_time, '%Y%m' ), ''',1, 0)) AS ''', DATE_FORMAT( c.login_time, '%Y%m' ), '''' )
)
FROM
user_login_record c INTO @sql ;
ELSE
SELECT
GROUP_CONCAT(
DISTINCT CONCAT( 'SUM(IF(DATE_FORMAT(login_time,''%Y%m%d'') = ''', DATE_FORMAT( c.login_time, '%Y%m%d' ), ''',1, 0)) AS ''', DATE_FORMAT( c.login_time, '%Y%m%d' ), '''' )
)
FROM
user_login_record c
WHERE DATEDIFF(beginTime,c.login_time)<=0 and DATEDIFF(c.login_time,endTime)<=0 INTO @sql ;
END IF ;
SELECT CONCAT( 'SELECT user_id as userId , ', @sql, ' from user_login_record GROUP BY user_id' ) INTO @sql;
PREPARE stmt FROM @SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
查询测试
call UserLoginTimesSatistics('2019/07/01','2019/07/03');