Sql containing a field period (start time, end time) and set to make a recording process

Question from a group of friends:

His blog links sql period of time with a problem and take the set, merge https://blog.csdn.net/Seandba/article/details/105152412 

Q: the total length of the open channel is calculated, as long as there is open passage even if any one terminal opening, difficulty is overlapped comprising various terminals Hours

aa128bd9b772d921814e068c67d5e7f4

Question test data

- a problem, the test data - calculating the total length of opening (h)
TRUNCATE TABLE xcp;
insert into xcp values('1','A1',to_date('20200317 01:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 06:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('2','A1',to_date('20200317 01:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 06:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('2','A1',to_date('20200317 01:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 08:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('2','A1',to_date('20200317 02:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 07:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('2','A1',to_date('20200317 03:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 07:00:00','yyyymmdd hh24:mi:ss'));

insert into xcp values('2','A1',to_date('20200317 05:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 09:00:00','yyyymmdd hh24:mi:ss '));
insert into xcp values('3','A1',to_date('20200317 09:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 11:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('3','A1',to_date('20200317 12:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 13:00:00','yyyymmdd hh24:mi:ss'));

insert into xcp values('2','A1',to_date('20200317 14:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 19:00:00','yyyymmdd hh24:mi:ss '));
insert into xcp values('3','A1',to_date('20200317 16:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 19:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('3','A1',to_date('20200317 18:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 19:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('3','A1',to_date('20200317 18:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 21:00:00','yyyymmdd hh24:mi:ss'));
commit;

SELECT * FROM xcp;

image2

The core issue is to seek union operations between multiple records, I wrote the following sql

--Question 1
WITH tmp1 AS (- all take time node
SELECT channel,BEGIN_TIME TIME FROM xcp
UNION SELECT channel,end_time FROM xcp
UNION SELECT channel,MIN(begin_time) FROM xcp GROUP BY channel
UNION SELECT channel,MAX(end_time) FROM xcp GROUP BY channel),

tmp2 AS (- each time a node is connected to the next node is formed period
SELECT a.channel,a.time,LEAD(a.time,1) OVER(PARTITION BY a.channel ORDER BY a.time) nexttime
FROM tmp1 a),

tmp3 AS (- taking a median of each period
SELECT b.channel,b.TIME,b.nexttime,(b.nexttime-b.time)/2+b.time midtime
FROM tmp2 b
WHERE b.nexttime IS NOT NULL),

tmp4 AS (- if the value in the original record of the period of time the channel or channels are not opened opening time
SELECT c.*,
CASE WHEN EXISTS (SELECT 1 FROM xcp o WHERE c.midtime BETWEEN o.begin_time AND o.end_time) THEN 1 ELSE 0 END *
(c.nexttime-c.time)*24 duration
FROM tmp3 c)

SELECT nvl (d.channel, 'the total duration') channels, d.TIME start time, d.nexttime end time,
SUM (duration) "on-time passage (hour)" FROM tmp4 d
GROUP BY rollup((d.channel,d.TIME,d.nexttime))
ORDER BY 2;

09e02bd2c2d7e12249c24dc5380b754Looking very garbage sql, implementation plan must refuse to record it for later query it

Principle it is time out node, not on the time period between two time node, an intermediate value to the original record table query, if, after this time and belong to the set, and then recorded on the requirements set and with


Question 2: When you open the channel of seeking long 17

- Problems 2, Test Data - Calculation of long open No. 27 (h)
TRUNCATE TABLE xcp;
insert into xcp values('13','A1',to_date('20200314 08:00:00','yyyymmdd hh24:mi:ss'),to_date('20200315 09:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('14','A1',to_date('20200317 08:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 09:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('15','A1',to_date('20200316 03:00:00','yyyymmdd hh24:mi:ss'),to_date('20200317 05:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('16','A1',to_date('20200317 08:00:00','yyyymmdd hh24:mi:ss'),to_date('20200318 10:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('17','A1',to_date('20200316 08:00:00','yyyymmdd hh24:mi:ss'),to_date('20200318 10:00:00','yyyymmdd hh24:mi:ss'));
insert into xcp values('18','A1',to_date('20200320 08:00:00','yyyymmdd hh24:mi:ss'),to_date('20200321 10:00:00','yyyymmdd hh24:mi:ss'));
commit;

SELECT * FROM xcp ORDER BY begin_time

image5sql as follows:

---- Question 2
WITH tmp1 AS (- all the time taken to join nodes 17 taken 0:00 17 and 24 at both time points
SELECT channel,BEGIN_TIME TIME FROM xcp
UNION SELECT channel,end_time FROM xcp
UNION SELECT channel,MIN(begin_time) FROM xcp GROUP BY channel
UNION SELECT channel,MAX(end_time) FROM xcp GROUP BY channel
UNION SELECT DISTINCT channel,to_date('20200317','yyyymmdd') FROM xcp
UNION SELECT DISTINCT channel,to_date('20200318','yyyymmdd') FROM xcp),

tmp2 AS (- each time a node is connected to the next node is formed period
SELECT a.channel,a.time,LEAD(a.time,1) OVER(PARTITION BY a.channel ORDER BY a.time) nexttime
FROM tmp1 a),

tmp3 AS (- taking a median of each period
SELECT b.channel,b.TIME,b.nexttime,(b.nexttime-b.time)/2+b.time midtime
FROM tmp2 b
WHERE b.nexttime IS NOT NULL
AND to_char(b.TIME,'yyyymmdd')=20200317),

tmp4 AS (- if the value in the original record of the period of time the channel or channels are not opened opening time
SELECT c.*,
CASE WHEN EXISTS (SELECT 1 FROM xcp o WHERE c.midtime BETWEEN o.begin_time AND o.end_time) THEN 1 ELSE 0 END *
(c.nexttime-c.time)*24 duration
FROM tmp3 c)

SELECT nvl (d.channel, 'the total duration') channels, d.TIME start time, d.nexttime end time,
SUM (duration) "on-time passage (hour)" FROM tmp4 d
GROUP BY rollup((d.channel,d.TIME,d.nexttime))
ORDER BY 2;

imageThe idea is to take the time point when the first step of separately added time point at 0:24 on the 17th point to





optimization:

The code five full table scan, garbage efficiency, small strong eighth case opposite consideration, small strong binding to the idea, the ability to tune to a full table scan, as follows

  - 8 characterized in: a recording start time is greater than the end time of the recording section; then put down this part of the time, and finally to lose
WITH tmp AS(
SELECT a.channel,a.begin_time,a.end_time,
(LEAD (a.begin_time, 1) OVER (PARTITION BY a.channel ORDER BY begin_time, end_time) - a.end_time) * 24 hoursto_next_begin_time - to the next record if the time interval is positive case 8
FROM xcp a) 

SELECT (MAX (end_time) -MIN (begin_time)) * 24 - sum (DECODE (sign (hoursto_next_begin_time), 1, hoursto_next_begin_time, 0)) channel opening time
FROM tmp aa

image

Guess you like

Origin www.cnblogs.com/yongestcat/p/12590154.html