小提琴:http://sqlfiddle.com/#!18/d7d80/6
数据:
CREATE TABLE schedule
([dte] date, [tme] time, [wkd] int);
INSERT INTO schedule
([dte], [tme], [wkd])
VALUES
('2020/01/01', '17:30', 15),
('2020/01/01', '18:00', 15),
('2020/01/01', '18:15', 15),
('2020/01/02', '17:30', 30),
('2020/01/02', '18:00', 30),
('2020/01/03', '17:30', 120),
('2020/01/04', '17:45', 45),
('2020/01/05', '17:45', 30),
('2020/01/06', '17:45', 15),
('2020/01/07', '18:00', 30);
该表由三列组成:日期,时间和分钟。工作时间和分钟数始终以15分钟为增量(整小时,15点过去,半小时,45点过去)。
问题:
我想显示一个简单的ASCI利用率图表,其中显示了工作时间和空闲时间。例如,对于以上数据,它可能类似于:
01/01| X XX
01/02| XXXX
01/03| XXXX
01/04| XXX
01/05| XX
01/06| X
01/07| XX
尝试的解决方案:
我已经开始以下查询:
with cte as (SELECT dte,
tme,
convert(time,DATEADD(MINUTE, wkd, tme)) as fns
FROM schedule)
SELECT dte,
max(case when CONVERT (TIME,{t '17:30:00'}) >= tme
and CONVERT (TIME,{t '17:45:00'}) <= fns then 'x' else null end),
max(case when CONVERT (TIME,{t '17:45:00'}) >= tme
and CONVERT (TIME,{t '18:00:00'}) <= fns then 'x' else null end),
max(case when CONVERT (TIME,{t '18:00:00'}) >= tme
and CONVERT (TIME,{t '18:15:00'}) <= fns then 'x' else null end),
max(case when CONVERT (TIME,{t '18:15:00'}) >= tme
and CONVERT (TIME,{t '18:30:00'}) <= fns then 'x' else null end)
FROM cte
GROUP BY dte
虽然它似乎可以正常工作,但如果我不得不将我正在查看的时间段更改为一个或两个小时或更长的时间,我已经可以看到这种方法确实很尴尬。
我确定有一个巧妙的技巧可以用来简化此查询。任何帮助将不胜感激。
我建议使用某种模板或过程来生成您的查询。从这个问题尚不清楚您是直接在SQL Server中直接运行查询还是手动在SQL Server数据库中运行某种应用程序。在第一种情况下,您可以创建一个存储过程,以根据时间单位间隔(在您的情况下为15分钟)为您生成查询。在第二个中,您可以使用正在使用的任何应用程序的后端来生成查询。
伪代码的一般情况是
// inputs
timeUnit = 15 min
rangeStart = 17:30:00
rangeEnd = 18:30:00
// algorithm
discreteTimes = toDiscreteTimes(rangeStart, rangeEnd, timeUnit) // calculate discrete times between rangeStart and rangeEnd, so in your case 17:30, 17:45, ..., 18:30
query = "..." // up to the start of your case statements
for (i = 1; i < discreteTimes.maxIndex; i++) {
query += caseStatement(discreteTimes[i-1], discreteTimes[i]) // generate your case statement with these two times
}
query += "..." // the rest of the query after the case statements