我会创建一个存储过程来完成这项工作。虽然可以在具有足够强制转换的表达式中完成,但这会令人不快。关键技巧是将一小时后的分钟数转换为CHAR(2) 字符串,然后可以自动转换为数字。 AFAIK,没有其他方法可以将区间转换为数字。
DROP PROCEDURE IF EXISTS Multiple_Of_Quarter_Hour;
CREATE PROCEDURE Multiple_Of_Quarter_Hour(dtval DATETIME YEAR TO MINUTE
DEFAULT CURRENT YEAR TO MINUTE)
RETURNING DATETIME YEAR TO MINUTE AS rounded_value;
DEFINE mm CHAR(2);
LET mm = EXTEND(dtval, MINUTE TO MINUTE);
LET dtval = dtval - mm UNITS MINUTE;
RETURN dtval + (15 * (mm / 15)::INTEGER) UNITS MINUTE;
END PROCEDURE;
DROP PROCEDURE IF EXISTS Multiple_Of_N_Minutes;
CREATE PROCEDURE Multiple_Of_N_Minutes(dtval DATETIME YEAR TO MINUTE
DEFAULT CURRENT YEAR TO MINUTE,
n_min INTEGER DEFAULT 15)
RETURNING DATETIME YEAR TO MINUTE AS rounded_value;
DEFINE mm CHAR(2);
LET mm = EXTEND(dtval, MINUTE TO MINUTE);
LET dtval = dtval - mm UNITS MINUTE;
RETURN dtval + (n_min * (mm / n_min)::INTEGER) UNITS MINUTE;
END PROCEDURE;
测试代码:
CREATE TEMP TABLE t_times (dtval DATETIME YEAR TO SECOND PRIMARY KEY);
INSERT INTO t_times VALUES('2016-05-27 00:00:00');
INSERT INTO t_times VALUES('2016-05-27 00:04:59');
INSERT INTO t_times VALUES('2016-05-27 00:06:59');
INSERT INTO t_times VALUES('2016-05-27 00:14:59');
INSERT INTO t_times VALUES('2016-05-27 00:15:00');
INSERT INTO t_times VALUES('2016-05-27 00:16:57');
INSERT INTO t_times VALUES('2016-05-27 00:21:00');
INSERT INTO t_times VALUES('2016-05-27 00:24:36');
INSERT INTO t_times VALUES('2016-05-27 00:25:11');
INSERT INTO t_times VALUES('2016-05-27 00:29:59');
INSERT INTO t_times VALUES('2016-05-27 00:30:00');
INSERT INTO t_times VALUES('2016-05-27 00:35:44');
INSERT INTO t_times VALUES('2016-05-27 00:44:59');
INSERT INTO t_times VALUES('2016-05-27 00:45:00');
INSERT INTO t_times VALUES('2016-05-27 00:49:53');
INSERT INTO t_times VALUES('2016-05-27 00:50:30');
INSERT INTO t_times VALUES('2016-05-27 00:59:59');
INSERT INTO t_times VALUES('2016-05-27 01:16:07');
INSERT INTO t_times VALUES('2016-05-27 01:34:10');
INSERT INTO t_times VALUES('2016-05-27 02:24:46');
INSERT INTO t_times VALUES('2016-05-27 04:32:08');
INSERT INTO t_times VALUES('2016-05-27 11:52:09');
INSERT INTO t_times VALUES('2016-05-27 14:00:28');
INSERT INTO t_times VALUES('2016-05-27 16:10:31');
INSERT INTO t_times VALUES('2016-05-27 17:46:58');
INSERT INTO t_times VALUES('2016-05-27 19:25:35');
INSERT INTO t_times VALUES('2016-05-27 22:52:48');
SELECT dtval,
Multiple_Of_Quarter_Hour(dtval) AS m15a,
EXTEND(Multiple_Of_N_Minutes(dtval, 2), HOUR TO MINUTE) AS m02,
EXTEND(Multiple_Of_N_Minutes(dtval, 3), HOUR TO MINUTE) AS m03,
EXTEND(Multiple_Of_N_Minutes(dtval, 4), HOUR TO MINUTE) AS m04,
EXTEND(Multiple_Of_N_Minutes(dtval, 5), HOUR TO MINUTE) AS m05,
EXTEND(Multiple_Of_N_Minutes(dtval, 6), HOUR TO MINUTE) AS m06
FROM t_times
ORDER BY dtval;
SELECT dtval,
EXTEND(Multiple_Of_N_Minutes(dtval, 10), HOUR TO MINUTE) AS m10,
EXTEND(Multiple_Of_N_Minutes(dtval, 12), HOUR TO MINUTE) AS m12,
EXTEND(Multiple_Of_N_Minutes(dtval, 15), HOUR TO MINUTE) AS m15b,
EXTEND(Multiple_Of_N_Minutes(dtval, 20), HOUR TO MINUTE) AS m20,
EXTEND(Multiple_Of_N_Minutes(dtval, 30), HOUR TO MINUTE) AS m30,
EXTEND(Multiple_Of_N_Minutes(dtval), HOUR TO MINUTE) AS m15c
FROM t_times
ORDER BY dtval;
示例输出:
dtval m15a m02 m03 m04 m05 m06
2016-05-27 00:00:00 2016-05-27 00:00 00:00 00:00 00:00 00:00 00:00
2016-05-27 00:04:59 2016-05-27 00:00 00:04 00:03 00:04 00:00 00:00
2016-05-27 00:06:59 2016-05-27 00:00 00:06 00:06 00:04 00:05 00:06
2016-05-27 00:14:59 2016-05-27 00:00 00:14 00:12 00:12 00:10 00:12
2016-05-27 00:15:00 2016-05-27 00:15 00:14 00:15 00:12 00:15 00:12
2016-05-27 00:16:57 2016-05-27 00:15 00:16 00:15 00:16 00:15 00:12
2016-05-27 00:21:00 2016-05-27 00:15 00:20 00:21 00:20 00:20 00:18
2016-05-27 00:24:36 2016-05-27 00:15 00:24 00:24 00:24 00:20 00:24
2016-05-27 00:25:11 2016-05-27 00:15 00:24 00:24 00:24 00:25 00:24
2016-05-27 00:29:59 2016-05-27 00:15 00:28 00:27 00:28 00:25 00:24
2016-05-27 00:30:00 2016-05-27 00:30 00:30 00:30 00:28 00:30 00:30
2016-05-27 00:35:44 2016-05-27 00:30 00:34 00:33 00:32 00:35 00:30
2016-05-27 00:44:59 2016-05-27 00:30 00:44 00:42 00:44 00:40 00:42
2016-05-27 00:45:00 2016-05-27 00:45 00:44 00:45 00:44 00:45 00:42
2016-05-27 00:49:53 2016-05-27 00:45 00:48 00:48 00:48 00:45 00:48
2016-05-27 00:50:30 2016-05-27 00:45 00:50 00:48 00:48 00:50 00:48
2016-05-27 00:59:59 2016-05-27 00:45 00:58 00:57 00:56 00:55 00:54
2016-05-27 01:16:07 2016-05-27 01:15 01:16 01:15 01:16 01:15 01:12
2016-05-27 01:34:10 2016-05-27 01:30 01:34 01:33 01:32 01:30 01:30
2016-05-27 02:24:46 2016-05-27 02:15 02:24 02:24 02:24 02:20 02:24
2016-05-27 04:32:08 2016-05-27 04:30 04:32 04:30 04:32 04:30 04:30
2016-05-27 11:52:09 2016-05-27 11:45 11:52 11:51 11:52 11:50 11:48
2016-05-27 14:00:28 2016-05-27 14:00 14:00 14:00 14:00 14:00 14:00
2016-05-27 16:10:31 2016-05-27 16:00 16:10 16:09 16:08 16:10 16:06
2016-05-27 17:46:58 2016-05-27 17:45 17:46 17:45 17:44 17:45 17:42
2016-05-27 19:25:35 2016-05-27 19:15 19:24 19:24 19:24 19:25 19:24
2016-05-27 22:52:48 2016-05-27 22:45 22:52 22:51 22:52 22:50 22:48
dtval m10 m12 m15b m20 m30 m15c
2016-05-27 00:00:00 00:00 00:00 00:00 00:00 00:00 00:00
2016-05-27 00:04:59 00:00 00:00 00:00 00:00 00:00 00:00
2016-05-27 00:06:59 00:00 00:00 00:00 00:00 00:00 00:00
2016-05-27 00:14:59 00:10 00:12 00:00 00:00 00:00 00:00
2016-05-27 00:15:00 00:10 00:12 00:15 00:00 00:00 00:15
2016-05-27 00:16:57 00:10 00:12 00:15 00:00 00:00 00:15
2016-05-27 00:21:00 00:20 00:12 00:15 00:20 00:00 00:15
2016-05-27 00:24:36 00:20 00:24 00:15 00:20 00:00 00:15
2016-05-27 00:25:11 00:20 00:24 00:15 00:20 00:00 00:15
2016-05-27 00:29:59 00:20 00:24 00:15 00:20 00:00 00:15
2016-05-27 00:30:00 00:30 00:24 00:30 00:20 00:30 00:30
2016-05-27 00:35:44 00:30 00:24 00:30 00:20 00:30 00:30
2016-05-27 00:44:59 00:40 00:36 00:30 00:40 00:30 00:30
2016-05-27 00:45:00 00:40 00:36 00:45 00:40 00:30 00:45
2016-05-27 00:49:53 00:40 00:48 00:45 00:40 00:30 00:45
2016-05-27 00:50:30 00:50 00:48 00:45 00:40 00:30 00:45
2016-05-27 00:59:59 00:50 00:48 00:45 00:40 00:30 00:45
2016-05-27 01:16:07 01:10 01:12 01:15 01:00 01:00 01:15
2016-05-27 01:34:10 01:30 01:24 01:30 01:20 01:30 01:30
2016-05-27 02:24:46 02:20 02:24 02:15 02:20 02:00 02:15
2016-05-27 04:32:08 04:30 04:24 04:30 04:20 04:30 04:30
2016-05-27 11:52:09 11:50 11:48 11:45 11:40 11:30 11:45
2016-05-27 14:00:28 14:00 14:00 14:00 14:00 14:00 14:00
2016-05-27 16:10:31 16:10 16:00 16:00 16:00 16:00 16:00
2016-05-27 17:46:58 17:40 17:36 17:45 17:40 17:30 17:45
2016-05-27 19:25:35 19:20 19:24 19:15 19:20 19:00 19:15
2016-05-27 22:52:48 22:50 22:48 22:45 22:40 22:30 22:45
显然,Multiple_Of_Quarter_Hour() 可以写成Multiple_Of_N_Minutes() 的简单封面。
单个表达式:
SELECT dtval,
(EXTEND(dtval, YEAR TO MINUTE) -
(EXTEND(dtval, MINUTE TO MINUTE)::CHAR(2)) UNITS MINUTE) +
(15 * ((EXTEND(dtval, MINUTE TO MINUTE)::CHAR(2)) / 15)::INTEGER) UNITS MINUTE
FROM t_times
ORDER BY dtval;
如果您必须多次编写该代码,那么不使用存储过程将是可笑的。
虽然有点棘手,但也可以舍入到最接近的 N 分钟倍数,而不是总是截断(例如,如果间隔是 10 分钟,则时间从 13:55:00 到 14:04 :59 将全部转换为 14:00)。
DROP PROCEDURE IF EXISTS Nearest_Multiple_Of_N_Minutes;
CREATE PROCEDURE Nearest_Multiple_Of_N_Minutes(dtval DATETIME YEAR TO SECOND
DEFAULT CURRENT YEAR TO SECOND,
n_min INTEGER DEFAULT 15)
RETURNING DATETIME YEAR TO MINUTE AS rounded_value;
DEFINE mm CHAR(2);
DEFINE dt_yy_mm DATETIME YEAR TO MINUTE;
LET dt_yy_mm = dtval + ((30 * n_min) UNITS SECOND);
LET mm = EXTEND(dt_yy_mm, MINUTE TO MINUTE);
LET dt_yy_mm = dt_yy_mm - mm UNITS MINUTE;
RETURN dt_yy_mm + (n_min * (mm / n_min)::INTEGER) UNITS MINUTE;
END PROCEDURE;
SELECT dtval,
Nearest_Multiple_Of_N_Minutes(dtval, 10) AS m10,
Nearest_Multiple_Of_N_Minutes(dtval, 15) AS m15,
Nearest_Multiple_Of_N_Minutes(dtval, 20) AS m20,
Nearest_Multiple_Of_N_Minutes(dtval, 30) AS m30
FROM t_times
ORDER BY dtval;
注意函数时间参数类型的变化。