I am trying to create a stored procedure that can filter on a full or partial time. It should only filter on hours or minutes (not seconds) or both hours and minutes.
Using the sample data below:
#StartTimeFilter = '09:15' --> should return record #1
#StartTimeFilter = '10' --> should return records 2, 3, 10
#StartTimeFilter = '5' --> should return records 1, 2, 5, 6, 7, 8, 9
#StartTimeFilter = '45' --> should return records 5, 6
#StartTimeFilter = '13:45' --> should return record #6
#StartTimeFilter = '11:' --> should return records 4, 5
Code:
CREATE TABLE test
(
id INT,
startTime DateTime
);
INSERT INTO test (id, startTime) VALUES (1, '2021-10-25 09:15:00');
INSERT INTO test (id, startTime) VALUES (2, '2021-10-25 10:15:00');
INSERT INTO test (id, startTime) VALUES (3, '2021-10-25 10:30:00');
INSERT INTO test (id, startTime) VALUES (4, '2021-10-25 11:30:00');
INSERT INTO test (id, startTime) VALUES (5, '2021-10-25 11:45:00');
INSERT INTO test (id, startTime) VALUES (6, '2021-10-25 13:45:00');
INSERT INTO test (id, startTime) VALUES (7, '2021-10-25 14:50:00');
INSERT INTO test (id, startTime) VALUES (8, '2021-10-25 15:51:00');
INSERT INTO test (id, startTime) VALUES (9, '2021-10-25 15:58:00');
INSERT INTO test (id, startTime) VALUES (10,'2021-10-25 16:10:00');
It looks like you need a simple like string comparision:
declare #StartTimeFilter varchar(10)='5'
select *
from test
where Convert(varchar(5),starttime,114) like Concat('%',#StartTimeFilter,'%')
I am trying to calculate average monthly value of premiums for each POLICY_ID in monthly basis as shown below. When a customer updates his/her yearly payment frequency to a value different than 12, I need to manually calculate the average monthly value for the PREMIUM. How can I achieve the values shown in MONTHLY _PREMIUM_DESIRED?
Thanks in advance.
Note: Oracle version 12c
What I've tried:
SELECT
T.*,
SUM(PREMIUM) OVER(PARTITION BY T.POLICY_ID ORDER BY T.POLICY_ID, T.PAYMENT_DATE ROWS BETWEEN CURRENT ROW AND 12/T.YEARLY_PAYMENT_FREQ-1 FOLLOWING ) / (12/T.YEARLY_PAYMENT_FREQ) MONTLY_PREMIUM_CALCULATED
FROM MYTABLE T
;
Code for data:
DROP TABLE MYTABLE;
CREATE TABLE MYTABLE (POLICY_ID NUMBER(11), PAYMENT_DATE DATE, PREMIUM NUMBER(5), YEARLY_PAYMENT_FREQ NUMBER(2),MONTHLY_PREMIUM_DESIRED NUMBER(5));
INSERT INTO MYTABLE VALUES (1, DATE '2014-10-01',120,12,120);
INSERT INTO MYTABLE VALUES (1, DATE '2014-11-01',360,4,120);
INSERT INTO MYTABLE VALUES (1, DATE '2014-12-01',0,4,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-01-01',0,4,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-02-01',360,4,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-03-01',0,4,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-04-01',0,4,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-05-01',720,2,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-06-01',0,2,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-07-01',0,2,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-08-01',0,2,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-09-01',0,2,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-10-01',0,2,120);
INSERT INTO MYTABLE VALUES (1, DATE '2015-11-01',120,12,120);
INSERT INTO MYTABLE VALUES (2, DATE '2015-01-01',60,3,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-02-01',0,3,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-03-01',0,3,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-04-01',0,3,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-05-01',180,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-06-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-07-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-08-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-09-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-10-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-11-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2015-12-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2016-01-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2016-02-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2016-03-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2016-04-01',0,1,15);
INSERT INTO MYTABLE VALUES (2, DATE '2016-05-01',15,12,15);
INSERT INTO MYTABLE VALUES (2, DATE '2016-06-01',15,12,15);
SELECT * FROM MYTABLE;
EDIT:
Regardless from payment frequency PREMIUM amount can also be changed by customer. Below, for the POLICY_ID = 1, I have added new records starting from "2015/11/01" to demonstrate this situation. In this case, average monthly premium increased from 120 to 240.
Also removed the screenshot to make the question more readable.
DROP TABLE MYTABLE2;
CREATE TABLE MYTABLE2 (POLICY_ID NUMBER(11), PAYMENT_DATE DATE, PREMIUM NUMBER(5), YEARLY_PAYMENT_FREQ NUMBER(2),MONTHLY_PREMIUM_DESIRED NUMBER(5));
INSERT INTO MYTABLE2 VALUES (1, DATE '2014-10-01',120,12,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2014-11-01',360,4,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2014-12-01',0,4,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-01-01',0,4,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-02-01',360,4,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-03-01',0,4,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-04-01',0,4,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-05-01',720,2,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-06-01',0,2,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-07-01',0,2,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-08-01',0,2,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-09-01',0,2,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-10-01',0,2,120);
INSERT INTO MYTABLE2 VALUES (1, DATE '2015-11-01',240,12,240);
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-12-01',240,12,240); --newly added records
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-01-01',960,4,240); --newly added records
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-02-01',0,4,240); --newly added records
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-03-01',0,4,240); --newly added records
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-04-01',0,4,240); --newly added records
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-05-01',960,4,240); --newly added records
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-06-01',0,4,240); --newly added records
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-07-01',0,4,240); --newly added records
INSERT INTO MYTABLE2 VALUES (1, DATE '2016-08-01',0,4,240); --newly added records
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-01-01',60,3,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-02-01',0,3,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-03-01',0,3,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-04-01',0,3,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-05-01',180,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-06-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-07-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-08-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-09-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-10-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-11-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2015-12-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2016-01-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2016-02-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2016-03-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2016-04-01',0,1,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2016-05-01',15,12,15);
INSERT INTO MYTABLE2 VALUES (2, DATE '2016-06-01',15,12,15);
SELECT * FROM MYTABLE2;
I think the calculation is:
select t.*,
premium / (12 / yearly_payment_freq)) as monthly_premium_calculated
from mytable t;
EDIT:
I see, you also need this spread over the intermediate months. So you can assign the groups by counting the number of non-zero payments. Then:
select t.*,
( max(premium) over (partition by policy_id, grp) /
(12 / yearly_payment_freq)
) as monthly_premium_calculated
from (select t.*,
sum(case when premium > 0 then 1 else 0 end) over (partition by policy_id order by payment_date) as grp
from mytable t
) t;
Here is a db<>fiddle (it uses Postgres because that is easier to set up than Oracle).
I am trying to get a closest Polling datetime to OrderSubmittedtime where the closest Polling datetime can be a datetime previous or future date(+ or -) compared to the OrderSubmittedtime as long as the datetime is close enough.
Below is the example for this :
create table Rosters
(
OrderID int,
PollingTime datetime
,OrdersubmittedTime datetime
)
insert into Rosters values (1,'2017-08-07 11:30:00.000','2017-08-07 04:12:51.000')
insert into Rosters values (1,'2017-08-07 12:13:34.000','2017-08-07 04:12:51.000')
insert into Rosters values (1,'2017-08-07 03:30:00.000','2017-08-07 04:12:51.000')
insert into Rosters values (1,'2017-08-08 00:30:00.000','2017-08-07 04:12:51.000')
insert into Rosters values (2,'2017-08-05 10:30:00.000','2017-08-07 04:12:51.000')
insert into Rosters values (2,'2017-08-06 11:30:00.000','2017-08-07 04:12:51.000')
insert into Rosters values (2,'2017-08-08 00:30:00.000','2017-08-07 04:12:51.000')
expected result set is :
for OrderID=1, the closest Polling Time will be '2017-08-07 03:30:00.000'
and for OrderID=2, the closest Polling Time will be '2017-08-06 11:30:00.000'
i could currently get to write a query like below, but it is not correct :
select PollingTime
,OrdersubmittedTime
,OrderID
, abs(DATEDIFF(MINUTE,OrdersubmittedTime,PollingTime)) as ClosestPollingTime
from Rosters
Kindly help me out , Thanks.
You can use an OUTER APPLY to join a subquery on the same table and take the closest value using your ClosestPollingTime like so (modified to filter on Seconds rather than minutes, based on comment from Damien_The_Unbeliever:
CREATE TABLE #Rosters
(
OrderID INT,
PollingTime DATETIME,
OrdersubmittedTime DATETIME
);
INSERT INTO #Rosters
VALUES
(1, '2017-08-07 11:30:00.000', '2017-08-07 04:12:51.000'),
(1, '2017-08-07 12:13:34.000', '2017-08-07 04:12:51.000'),
(1, '2017-08-07 03:30:00.000', '2017-08-07 04:12:51.000'),
(1, '2017-08-08 00:30:00.000', '2017-08-07 04:12:51.000'),
(2, '2017-08-05 10:30:00.000', '2017-08-07 04:12:51.000'),
(2, '2017-08-06 11:30:00.000', '2017-08-07 04:12:51.000'),
(2, '2017-08-08 00:30:00.000', '2017-08-07 04:12:51.000');
SELECT r.OrdersubmittedTime,
r.OrderID,
t.ClosestPollingTime
FROM #Rosters AS r
OUTER APPLY
(
SELECT TOP 1
r2.OrderID,
r2.PollingTime as ClosestPollingTime
FROM #Rosters AS r2
WHERE r2.OrderID = r.OrderID
ORDER BY ABS(DATEDIFF(SECOND, r2.OrdersubmittedTime, r2.PollingTime))
) t
GROUP BY r.OrdersubmittedTime,
r.OrderID,
t.ClosestPollingTime;
DROP TABLE #Rosters;
Produces:
OrdersubmittedTime OrderID ClosestPollingTime
2017-08-07 04:12:51.000 1 2017-08-07 03:30:00.000
2017-08-07 04:12:51.000 2 2017-08-06 11:30:00.000