专注大数据培训
我们一直在领跑

最新面试题集锦(16)

派工记录表

#数据示例 insert into work_plan values
(‘张三’,’2020-01-01′,null,’06:30′),
(‘李四’,’2020-02-01′,’2020-02-15′,’07:00′),
(‘王五’,’2019-12-29′,’2020-03-30′,’06:00′),
(‘赵六’,’2019-12-29′,’2020-03-30′,’06:00′)

create table work_plan
(
worker_name varchar(10), #工人名字
start_date date, #派工开始日期
end_date date,  #派工结束日期
sign_time varchar(10) #要求到岗时间
)

1、表示某人从某日开始到某日结束,按要求工作,派工期间每日打卡时间必须在“要求到岗时间”前(含要求时间,精确到分钟),否则迟到。
例如:
要求7:00,则6:59或者7:00:59 都不算迟到;7:01则视为迟到1分钟
2、行1中“派工结束日期”为null,表示此人的工作结束时间尚未确定,还在搬砖中;
行2中派工结束日期为2020-02-15,表示派工于02-15日结束。
3、假设员工名字不重复,每人只有一条派工信息

打卡记录表

#数据示例 insert into sign_log values
(‘张三’,’2020-02-16 04:01′),
(‘张三’,’2020-02-16 05:02′),
(‘张三’,’2020-02-16 06:03′),
(‘王五’,’2020-02-16 07:03′),
(‘王五’,’2020-02-16 08:03′),
(‘王五’,’2020-02-16 09:03′)

create table sign_log
(
worker_name varchar(10),
sign_time datetime #实际打卡时间
)

在员工每次按指纹考勤时
都会生成一条记录

要求

写一个存储过程,输入参数:日期(date),输出表格

例如 call attendance(“2020-02-16”)

输出表格如下:

注:
1、2020-02-16李四派工期已结束,不在派工期间不需要计算考勤,故不用显示
2、赵六在当日没有打卡,按照迟到算,迟到时间1440分钟
3、迟到时间以分钟为单位,取正整数(包含0)

思路

我们要最终得到迟到时间,需要用表二中最早的打卡时间减去表一中要求的截至打卡时间,但很明显两个表日期的数据格式不一致,对表一的时间数据 sing_time 我们需要和年份进行拼接,然后再与表二的打卡时间进行比较,即可得出最终我们需要的迟到时间。

但在实际写查询语句时,我发现那样会过于繁琐,变考虑将上述步骤通过 SQL 中自定义函数来实现。先来复习下MySQL中的自定义函数。

自定义函数实例:

先来一个简单的,创建一个函数将'2009-06-23 00:00:00'这样格式的datetime时间转化为'2009年6月23日0时0分0秒'这样的格式:

DELIMITER $$
DROP FUNCTION IF EXISTS `sp_test`.`getdate`$$
CREATE FUNCTION `sp_test`.`getdate`(gdate datetime) RETURNS varchar(255)
BEGIN
DECLARE x VARCHAR(255) DEFAULT '';
SET x= date_format(gdate,'%Y年%m月%d日%h时%i分%s秒');
RETURN x;
END $$
DELIMITER ;

解析:

第一句是定义一个结束标识符,因为MySQL默认是以分号作为SQL语句的结束符的,而函数体内部要用到分号,所以会跟默认的SQL结束符发生冲突,所以需要先定义一个其他的符号作为SQL的结束符;

第二句是如果这个函数已经存在了,就删除掉,sp_test是数据库的名字,函数是跟数据库相关联的,getdate是函数的名字;

第三句是创建一个函数,()里是参数的名字和类型,RETURNS 定义这个函数返回值的类型;

函数体必须放在BEGIN END之间;

DECLARE 是定义函数体的变量,这里定义一个变量x,默认是空,然后SET给x变量赋值;

RETURN 是返回值,这里把变量x返回,x的类型必须与第三句中定义的返回类型一致。

调用:

SELECT getdate(‘2009-06-23 00:00:00’);

返回 ‘2009年06月23日00时00分00秒’

最终答案

我们先来完成时间处理的自定义函数,代码如下:

DELIMITER $$
DROP FUNCTION IF EXISTS func_date_sub $$
-- d1 6:00 d2 '2020-2-16 4:5:0'
CREATE FUNCTION func_date_sub(d1 VARCHAR(20),d2 DATETIME) RETURNS INT
BEGIN
  IF d2 IS NULL THEN
	RETURN -1440;
  ELSE
	RETURN CEIL((UNIX_TIMESTAMP(CONCAT('2020-2-16 ',d1))-UNIX_TIMESTAMP(d2))/60);
  END IF;
  END $$
DELIMITER ;

SQL 查询语句如下:

select res.worker_name,res.attend,if(res.latetime<0,'是','否') as isLate,if(
res.latetime<0,abs(res.latetime),0) as latetime from
(select ck.worker_name,ck.attend,func_date_sub(ck.sign_time,ck.st) latetime
from (select e.worker_name,e.sign_time,'2020-02-16' as attend,k.st from 
(select * from work_plan 
where datediff(end_date,'2020-2-16')>0 
or end_date is null) e 
left join
(select worker_name,min(sign_time) st 
from sign_log group by worker_name) k 
on e.worker_name = k.worker_name) ck)res;
欢迎分享,转载有奖:多易教育 » 最新面试题集锦(16)