我的问题是关于收集时间列的可能性,特别是因为数据类型是
varchar2
:
CREATE TABLE t_video
(
video_id NUMBER NOT NULL ENABLE,
video_duration VARCHAR2(30 BYTE),
object_video VARCHAR2(1000 BYTE),
CONSTRAINT T_VIDEO_PK PRIMARY KEY ( VIDEO_ID )
);
INSERT INTO t_video (video_id, video_duration, object_video)
VALUES (1,'00:12:20',song);
INSERT INTO t_video (video_id, video_duration, object_video)
VALUES (2,'02:50:30',film);
然后我尝试并成功解决了问题如下:
-- code sum hours , minutes, seconds in three column
SELECT
SUM(to_char(substr(video_duration, - 8, 2))) AS hours,
SUM(to_char(substr(video_duration, - 5, 2))) / 60 AS minutes,
SUM(to_char(substr(video_duration, - 2, 2))) / 60 / 60 AS seconds
FROM
t_video;
-- code sum hours , minutes, seconds in one column
SELECT
id_user,
SUM(ROUND(h1 + h2 + h3, 2)) AS total_hours
FROM
(SELECT
id_user,
to_char(substr(video_duration, -8, 2)) AS h1,
to_char(substr(video_duration, -5, 2)) / 60 AS h2,
to_char(substr(video_duration, -2, 2)) / 60 / 60 AS h3
FROM
t_video)
GROUP BY
ROLLUP(id_user);
我只将时间转换为HH24,得到了所需的结果,如下:
SELECT id_user,
CAST(SUM(
EXTRACT(HOUR FROM
video_duration) * 60 * 60 +
EXTRACT(MINUTE FROM
video_duration) * 60 +
EXTRACT(SECOND FROM
video_duration)) *
INTERVAL '24' SECOND AS
INTERVAL DAY(1) TO
SECOND(0)) AS
total_duration
FROM
t_video
GROUP BY ROLLUP(id_user);
RESULT
id_user video_duration
------- ------------------
10 + 241 07: 39: 36
------------------------------
20 + 75 13: 40: 00
------------------------------
NULL + 316 21: 19: 36
如果您要存储时间,您可以使用
INTERVAL DAY(0) TO SECOND(0)
数据类型(而不是字符串),然后您的查询可以是:
SELECT video_id,
SUM(
EXTRACT(HOUR FROM video_duration) * 60 * 60
+ EXTRACT(MINUTE FROM video_duration) * 60
+ EXTRACT(SECOND FROM video_duration)
) * INTERVAL '1' SECOND AS total_duration
FROM t_video
GROUP BY ROLLUP(video_id);
对于样本数据:
CREATE TABLE t_video
(
video_id NUMBER NOT NULL ENABLE,
video_duration INTERVAL DAY(0) TO SECOND(0),
object_video VARCHAR2(1000 BYTE),
CONSTRAINT T_VIDEO_PK PRIMARY KEY ( VIDEO_ID )
);
INSERT INTO t_video (video_id, video_duration, object_video)
VALUES (1, INTERVAL '00:12:20' HOUR TO SECOND,'song');
INSERT INTO t_video (video_id, video_duration, object_video)
VALUES (2, INTERVAL '02:50:30' HOUR TO SECOND,'film');
输出:
视频_ID | TOTAL_DURATION |
---|---|
1 | +000000000 00:12:20.000000000 |
2 | +000000000 02:50:30.000000000 |
空 | +000000000 03:02:50.000000000 |
如果您想以不同的方式格式化它,您可以从默认的
INTERVAL DAY(9) TO SECOND(9)
转换为精度更小的间隔,例如 INTERVAL DAY(1) TO SECOND(0)
:
SELECT video_id,
CAST(
SUM(
EXTRACT(HOUR FROM video_duration) * 60 * 60
+ EXTRACT(MINUTE FROM video_duration) * 60
+ EXTRACT(SECOND FROM video_duration)
) * INTERVAL '1' SECOND
AS INTERVAL DAY(1) TO SECOND (0)
) AS total_duration
FROM t_video
GROUP BY ROLLUP(video_id);
视频_ID | TOTAL_DURATION |
---|---|
1 | +0 00:12:20 |
2 | +0 02:50:30 |
空 | +0 03:02:50 |
interval day to second
。然后你就可以使用Oracle内置的时间间隔函数。
-- Make a new interval day to second column.
alter table t_video add video_duration_new interval day to second;
-- Translate your string durations into intervals.
-- to_dsinterval requires a day, so we add 0 days. This assumes all your video durations are all HH:MM:SS
update t_video set video_duration_new = to_dsinterval(concat('0 ', video_duration));
-- Drop the old column.
alter table t_video drop column video_duration;
-- Replace it with the interval column.
alter table t_video rename column video_duration_new to video_duration;
现在使用
extract
即可轻松获取小时数。
select extract(hour from video_duration) from t_video;
这也可以为性能建立索引,并将检查值的格式是否正确。
示范.