BITAND SQL - Operation between hexadecimal data Oracle - sql

I need resolve the following situation:
I have the following twelve rows in a table A_5MIN_TST1 (the data to be compared are hexa, but examples works with decimal values):
UTCTIME|TLQ_INST
01/08/2013 01:05:00 a.m.|32
01/08/2013 01:10:00 a.m.|128
01/08/2013 01:15:00 a.m.|8
01/08/2013 01:20:00 a.m.|32
01/08/2013 01:25:00 a.m.|1
01/08/2013 01:30:00 a.m.|10
01/08/2013 01:35:00 a.m.|100
01/08/2013 01:40:00 a.m.|1000
01/08/2013 01:45:00 a.m.|2000
01/08/2013 01:50:00 a.m.|3000
01/08/2013 01:55:00 a.m.|4000
Doing a select I must analyze each bit of the tlq_inst column (hexadecimal data) and decide:
If some value of tlq_inst is
= 8
or
= 32
or
= 128
then write = 8.
When tlq_inst doesn't is 8, 32, 128 then write the first value of tlq_inst, over the range.
I have tried with this query:
SELECT DECODE(POWER(2,BITAND(tlq_inst, 168)), 1, 'OK','Q') salida
FROM A_5MIN_TST1
WHERE utctime >= TO_DATE ('01/08/2013 01:00:01','dd/mm/yyyy hh24:mi:ss')
AND utctime < TO_DATE ('01/08/2013 02:00:00','dd/mm/yyyy hh24:mi:ss')
AND POINTNUMBER = 330062;
And I received these results:
SALIDA
Q
Q
Q
Q
OK
Q
Q
Q
Q
Q
Q
Q
Resuming, on these 12 values, I need to do:
Get 'Q' if the comparison condition with mask is met.
Get the first value of tlq_inst, when the comparison with the mask, is NOT true.
If possible, do the same but inside where
With this query I managed to get 12 values, but I need to get only one.
Could you help me to resolve this problem?
CREATE TABLE A_5MIN_TST1
(
UTCTIME DATE NOT NULL,
POINTNUMBER INTEGER NOT NULL,
SITEID INTEGER,
VALOR_INST FLOAT(126),
TLQ_INST INTEGER,
VALOR_PROM FLOAT(126),
TLQ_PROM INTEGER,
VALOR_MAX FLOAT(126),
TLQ_MAX INTEGER,
UTCTIME_MAX DATE,
VALOR_MIN FLOAT(126),
TLQ_MIN INTEGER,
UTCTIME_MIN DATE
)
TABLESPACE USERS
PCTUSED 0
PCTFREE 10
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS UNLIMITED
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;
ALTER TABLE A_5MIN_TST1 ADD (
PRIMARY KEY
(UTCTIME, POINTNUMBER)
USING INDEX
TABLESPACE USERS
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS UNLIMITED
PCTINCREASE 0
));
SET DEFINE OFF;
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:05:00', 'MM/DD/YYYY HH24:MI:SS'), 32);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:10:00', 'MM/DD/YYYY HH24:MI:SS'), 128);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:15:00', 'MM/DD/YYYY HH24:MI:SS'), 8);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:20:00', 'MM/DD/YYYY HH24:MI:SS'), 32);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:25:00', 'MM/DD/YYYY HH24:MI:SS'), 1);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:30:00', 'MM/DD/YYYY HH24:MI:SS'), 10);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:35:00', 'MM/DD/YYYY HH24:MI:SS'), 100);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:40:00', 'MM/DD/YYYY HH24:MI:SS'), 1000);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:45:00', 'MM/DD/YYYY HH24:MI:SS'), 2000);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:50:00', 'MM/DD/YYYY HH24:MI:SS'), 3000);
Insert into A_5MIN_TST1
(UTCTIME, TLQ_INST)
Values
(TO_DATE('08/01/2013 01:55:00', 'MM/DD/YYYY HH24:MI:SS'), 4000);
COMMIT;

Here is a statement giving you Q when at least one record matches the bitmask and the earliest TLQ_INST otherwise. It uses KEEP DENSE_RANK. It orders the records by utctime, gets the earliest record and returns the tlq_inst of that record. In case there are more records with the same earliest time, it returns the maximum tlq_inst of these records.
select
case when max(bitand(tlq_inst, 168)) = 0 then
max(tlq_inst) keep (dense_rank first order by utctime)
else
'Q'
end as result
from a_5min_tst1
where utctime >= to_date ('01/08/2013 01:00:01','dd/mm/yyyy hh24:mi:ss')
and utctime < to_date ('01/08/2013 02:00:00','dd/mm/yyyy hh24:mi:ss')
and pointnumber = 330062;

Related

Oracle SQL Join columns on 2 conditions

I tried to search forums for my scenario but could not find anything remotely similar. So here goes my long winded explanation : I have 3 tables - order_fact , session_fact and orderline.
create table order_fact (order_no varchar2(20), order_timestamp date, cookie_id number, session_id number);
insert into order_fact values ('69857-20210329', to_date('29-MAR-2021 10:11:58', 'DD-MON-YYYY HH24:MI:SS'), 827678, 79853421);
insert into order_fact values ('78345-20210411', to_date('11-APR-2021 18:37:07', 'DD-MON-YYYY HH24:MI:SS'), 569834, 84886798);
insert into order_fact values ('79678-20210519', to_date('19-MAY-2021 20:51:34', 'DD-MON-YYYY HH24:MI:SS'), 589623, 89556782);
insert into order_fact values ('78759-20210411', to_date('11-APR-2021 09:46:52', 'DD-MON-YYYY HH24:MI:SS'), 685213, 77549823);
create table session_fact (cookie_id number, session_id number, session_timestamp date, marketing_vendor varchar2(30) , referral_type VARCHAR2(2) );
insert into session_fact values (827678, 79853421, to_date('29-MAR-2021 09:47:36', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (827678, 79853378, to_date('28-MAR-2021 12:47:36', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (827678, 79853313, to_date('24-MAR-2021 13:23:36', 'DD-MON-YYYY HH24:MI:SS'), 'Naaptol', 'S');
insert into session_fact values (827678, 79853254, to_date('23-MAR-2021 14:39:56', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886798, to_date('11-APR-2021 14:41:44', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886735, to_date('10-APR-2021 11:03:44', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886687, to_date('08-APR-2021 17:26:49', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886659, to_date('03-APR-2021 11:03:44', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886497, to_date('01-APR-2021 07:59:08', 'DD-MON-YYYY HH24:MI:SS'), 'Google', 'R');
insert into session_fact values (685213, 77549823, to_date('11-APR-2021 09:07:34', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (685213, 77549786, to_date('09-APR-2021 20:51:34', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (685213, 77549589, to_date('07-APR-2021 14:11:57', 'DD-MON-YYYY HH24:MI:SS'), 'FabShopping', 'D');
insert into session_fact values (685213, 77548356, to_date('03-APR-2021 15:38:42', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (589623, 89556782, to_date('19-MAY-2021 16:46:52', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (589623, 89556512, to_date('18-MAY-2021 09:46:52', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (589623, 89556477, to_date('13-MAY-2021 18:34:29', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (589623, 89556348, to_date('10-MAY-2021 16:13:49', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
create table orderline (order_no varchar2(20), ol_nbr number, ol_ref varchar2(5));
insert into orderline values ('78345-20210411', 0, '-2');
insert into orderline values ('78345-20210411', 1, 'HV3');
insert into orderline values ('78345-20210411', 2, 'HV3');
insert into orderline values ('78759-20210411', 0, '-2');
insert into orderline values ('78759-20210411', 1, 'PS5');
insert into orderline values ('78759-20210411', 2, 'PS5');
insert into orderline values ('78759-20210411', 3, 'PS5');
insert into orderline values ('79678-20210519', 0, '-2');
insert into orderline values ('79678-20210519', 1, 'NPT');
insert into orderline values ('79678-20210519', 2, 'NPT');
insert into orderline values ('69857-20210329', 0, '-2');
insert into orderline values ('69857-20210329', 1, 'HV3');
insert into orderline values ('69857-20210329', 2, 'HV3');
insert into orderline values ('69857-20210329', 3, 'HV3');
As can be seen from above order_fact and session_fact tables are connected by cookie and session id. The request is to get these columns : ORDER_NO, MARKETING_VENDOR, REFERRAL_TYPE, OL_REF from the above 3 tables.
I have written the JOIN query :
select a.ORDER_NO, b.MARKETING_VENDOR,
b.REFERRAL_TYPE, c.OL_REF
FROM order_fact a
INNER JOIN session_fact b
ON (a.cookie_id = b.COOKIE_ID AND
b.session_timestamp < a.order_timestamp AND
b.session_timestamp > a.order_timestamp-7)
INNER JOIN orderline c ON
(a.ORDER_NO = c.ORDER_NO AND c.OL_NBR = 1);
Here is the sticky situation for me :
Get the data in session_fact table for a cookie_id in order_fact for timestamp of not more than 7 days before the order_timestamp. For example - order_no 78345-20210411 was placed on 11-APR-2021 18:37:07. Using the cookie id of that order I get all rows in session_fact till 11-APR - 7 days = 4-APR. So 3rd and 1st Apr data cannot be considered. This has been taken care in my query. But I wanted to mention why I had the additional AND clauses in the 1st JOIN ON condition.
From the data got in point 1 above do not consider those records where REFERRAL_TYPE = 'D' and MARKETING_VENDOR = '-1'. 'S' and '-1' can be considered and so is 'R' and '-1'. Basically any values can be considered as long as its NOT 'D' and '-1'. And select the record whose timestamp is closest to the order_timestamp in table order_fact. Now this is where it gets tricky - if there are no records of past 7 days where combo of REFERRAL_TYPE and MARKETING_VENDOR is NOT 'D' and '-1' then join the tables order_fact and session_fact on both cookie_id and session_id and fetch the values.
Join tables order_fact and orderline ON ORDER_NO and OL_NBR = 1. This also has been taken care in my join query.
So my only problem is getting the JOIN between session_fact and order_fact on the 2 different conditions mentioned in point 2. Can this be done by SQL? The Tech Lead of my team asked me to write a PL/SQL block. I did that because the original request was to add MARKETING_VENDOR, REFERRAL_TYPE, OL_REF columns in order_fact table and get the values from their respective tables. I cannot help but feel this can be done by SQL using CASE. Or am I wrong? If anyone could please help me with this query I will be grateful.
Edit : Adding the result data set
Edit : Any kind soul to help me out? 🙂 I take it it's not possible in a SQL statement.
And select the record whose timestamp is closest to the order_timestamp in table order_fact
From your description looks like you just need Top 1 record by session_timestamp:
with
step1 as (
SELECT
a.ORDER_NO
,a.order_timestamp
,c.MARKETING_VENDOR
,c.REFERRAL_TYPE
,c.session_timestamp
FROM order_fact a
cross apply (
select *
from session_fact b
where a.cookie_id = b.COOKIE_ID
and (REFERRAL_TYPE,MARKETING_VENDOR) not in (('D','-1'))
AND b.session_timestamp < a.order_timestamp
--AND b.session_timestamp > a.order_timestamp-7
order by b.session_timestamp desc
fetch first 1 rows only
) c
)
select
s.*
,o.OL_REF
FROM
step1 s
JOIN orderline o
ON (s.ORDER_NO = o.ORDER_NO AND o.OL_NBR = 1)
;
Result:
ORDER_NO ORDER_TIMESTAMP MARKETING_VENDOR REFERRAL_TYPE SESSION_TIMESTAMP OL_REF
-------------- ------------------- ---------------- ------------- ------------------- ------
78345-20210411 2021-04-11 18:37:07 Google R 2021-04-01 07:59:08 HV3
78759-20210411 2021-04-11 09:46:52 FabShopping D 2021-04-07 14:11:57 PS5
69857-20210329 2021-03-29 10:11:58 Naaptol S 2021-03-24 13:23:36 HV3

Calculate difference in hours/days between different actions by a same user sql

I have a table where users perform an order action. I want to get difference in dates between his two or more orders. And similar for all users and then calculate their average or median.
Another issue is the order rows are duplicates because of another column in the table called order_received time which are 5 secs apart due to this two rows are created for the same users with same order time.
Based on your comment on my initial answer here is another worksheet.
Table DDL
create table tbl_order(
order_id integer,
account_number integer,
ordered_at date
);
Data as in other thread you pointed out
insert into tbl_order values (1, 1001, to_date('10-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (2, 2001, to_date('01-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (3, 2001, to_date('03-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (4, 1001, to_date('12-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (5, 3001, to_date('18-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (6, 1001, to_date('20-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
Query
WITH VW AS (
SELECT ACCOUNT_NUMBER,
MIN(ORDERED_AT) EARLIEST_ORDER_AT,
MAX(ORDERED_AT) LATEST_ORDER_AT,
ROUND(MAX(ORDERED_AT) - MIN(ORDERED_AT), 5) DIFF_IN_DAYS,
COUNT(*) TOTAL_ORDER_COUNT
FROM TBL_ORDER
GROUP BY ACCOUNT_NUMBER
)
SELECT ACCOUNT_NUMBER, EARLIEST_ORDER_AT, LATEST_ORDER_AT,
DIFF_IN_DAYS, ROUND( DIFF_IN_DAYS/TOTAL_ORDER_COUNT, 4) AVERAGE
FROM VW;
Result
===========Initial answer hereafter===========
Your question is not entirely clear, for example
Do you want difference in date per day (a user can make multiple orders per day) or just between their earliest and latest orders
What do you mean by average is it just (latest order date - earliest order date) / total purchase? This will be hours / purchase. is it even useful?
Anyways, here is a working sheet, this will give enough to set you in right direction (hopefully). This is for Oracle database, will work mostly for other database except the time conversion functions used here. You will have to search and use equivalent functions for database of your choice, if its not Oracle.
Create table
create table tbl_order(
order_id integer,
user_id integer,
item varchar2(100),
ordered_at date
);
Insert some data
insert into tbl_order values (8, 1, 'A2Z', to_date('21-Mar-2019 16:30:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (1, 1, 'ABC', to_date('22-Mar-2019 07:30:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (2, 1, 'ABC', to_date('22-Mar-2019 07:30:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (3, 1, 'EFGT', to_date('22-Mar-2019 09:30:30', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (4, 1, 'XYZ', to_date('22-Mar-2019 12:38:50', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (5, 1, 'ABC', to_date('22-Mar-2019 16:30:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (6, 2, 'ABC', to_date('22-Mar-2019 14:20:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (7, 2, 'A2C', to_date('22-Mar-2019 14:20:50', 'DD-MON-YYYY HH24:MI:SS'));
Get latest, earliest and total_purchase per user and an average
WITH VW AS (
SELECT USER_ID,
TO_CHAR(MIN(ORDERED_AT), 'DD-MON-YYYY HH24:MI:SS') EARLIEST_ORDER_AT,
TO_CHAR(MAX(ORDERED_AT), 'DD-MON-YYYY HH24:MI:SS')LATEST_ORDER_AT,
ROUND(MAX(ORDERED_AT) - MIN(ORDERED_AT), 5) * 24 DIFF_IN_HOURS,
COUNT(*) TOTAL_ORDER_COUNT
FROM TBL_ORDER
GROUP BY USER_ID
)
SELECT USER_ID, EARLIEST_ORDER_AT, LATEST_ORDER_AT,
DIFF_IN_HOURS, DIFF_IN_HOURS/TOTAL_ORDER_COUNT AVERAGE
FROM VW;
Get latest, earliest and total_purchase per user per day and an average
WITH VW AS (
SELECT USER_ID, TO_CHAR(ORDERED_AT, 'DD-MON-YYYY') ORDER_DATE_PART,
TO_CHAR(MIN(ORDERED_AT), 'DD-MON-YYYY HH24:MI:SS') EARLIEST_ORDER_AT,
TO_CHAR(MAX(ORDERED_AT), 'DD-MON-YYYY HH24:MI:SS')LATEST_ORDER_AT,
ROUND(MAX(ORDERED_AT) - MIN(ORDERED_AT), 5) * 24 DIFF_IN_HOURS,
COUNT(*) TOTAL_ORDER_COUNT
FROM TBL_ORDER
GROUP BY USER_ID, TO_CHAR(ORDERED_AT, 'DD-MON-YYYY')
)
SELECT USER_ID, ORDER_DATE_PART, EARLIEST_ORDER_AT, LATEST_ORDER_AT,
DIFF_IN_HOURS, DIFF_IN_HOURS/TOTAL_ORDER_COUNT AVERAGE
FROM VW;

7 day cumulative sum that resets on condition

I am trying to write a script that counts every time a customer spends more than €1200 within 7 days. Once a customer exceeds the €1200 threshold the cumulative sum should reset. For example, if a customer exceeded €1200 on day 3 this counts as 1 and the cumulative sum should reset on day 4.
I have seen similar questions which cover a resetting cumulative sum. None of these solutions work with the 7 day rolling condition.
Example Data Set
create table test2
(
yyyymmdd DATE not null,
account_id NUMBER,
vol_eur NUMBER
);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('21-01-2018 11:16:19', 'dd-mm-yyyy hh24:mi:ss'), 57642, 1500);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('06-01-2018 09:51:23', 'dd-mm-yyyy hh24:mi:ss'), 57645, 190);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('21-01-2018 07:09:35', 'dd-mm-yyyy hh24:mi:ss'), 57645, 300);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('03-01-2018 14:58:14', 'dd-mm-yyyy hh24:mi:ss'), 57646, 1000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('17-01-2018 13:30:44', 'dd-mm-yyyy hh24:mi:ss'), 57646, 130);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('03-01-2018 18:33:33', 'dd-mm-yyyy hh24:mi:ss'), 57647, 1000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('04-01-2018 08:44:33', 'dd-mm-yyyy hh24:mi:ss'), 57647, 270);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('05-01-2018 19:28:08', 'dd-mm-yyyy hh24:mi:ss'), 57647, 800);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('13-01-2018 12:24:21', 'dd-mm-yyyy hh24:mi:ss'), 57647, 700);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('15-01-2018 10:52:50', 'dd-mm-yyyy hh24:mi:ss'), 57647, 1000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('27-01-2018 12:07:20', 'dd-mm-yyyy hh24:mi:ss'), 57647, 500);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('10-01-2018 21:14:46', 'dd-mm-yyyy hh24:mi:ss'), 57647, 690);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('30-01-2018 15:39:17', 'dd-mm-yyyy hh24:mi:ss'), 57647, 5500);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('05-01-2018 19:43:38', 'dd-mm-yyyy hh24:mi:ss'), 57649, 300);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('06-01-2018 17:54:30', 'dd-mm-yyyy hh24:mi:ss'), 57649, 150);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('15-01-2018 19:38:36', 'dd-mm-yyyy hh24:mi:ss'), 57649, 1000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('20-01-2018 13:26:34', 'dd-mm-yyyy hh24:mi:ss'), 57649, 1150);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('06-01-2018 17:09:54', 'dd-mm-yyyy hh24:mi:ss'), 57651, 300);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('28-01-2018 17:31:14', 'dd-mm-yyyy hh24:mi:ss'), 57651, 250);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('04-01-2018 13:39:06', 'dd-mm-yyyy hh24:mi:ss'), 57654, 150);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('07-01-2018 13:18:26', 'dd-mm-yyyy hh24:mi:ss'), 57654, 200);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('13-01-2018 19:44:08', 'dd-mm-yyyy hh24:mi:ss'), 57654, 150);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('21-01-2018 16:18:05', 'dd-mm-yyyy hh24:mi:ss'), 57654, 150);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('28-01-2018 10:53:03', 'dd-mm-yyyy hh24:mi:ss'), 57654, 60);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('01-01-2018 12:09:00', 'dd-mm-yyyy hh24:mi:ss'), 57655, 1000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('01-01-2018 17:01:27', 'dd-mm-yyyy hh24:mi:ss'), 57655, 1000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('02-01-2018 19:30:31', 'dd-mm-yyyy hh24:mi:ss'), 57655, 200);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('21-01-2018 15:52:29', 'dd-mm-yyyy hh24:mi:ss'), 57655, 1000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('21-01-2018 16:58:52', 'dd-mm-yyyy hh24:mi:ss'), 57655, 500);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('11-01-2018 14:26:30', 'dd-mm-yyyy hh24:mi:ss'), 57661, 2000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('12-01-2018 21:54:25', 'dd-mm-yyyy hh24:mi:ss'), 57661, 500);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('06-01-2018 16:46:25', 'dd-mm-yyyy hh24:mi:ss'), 57666, 5000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('10-01-2018 18:27:51', 'dd-mm-yyyy hh24:mi:ss'), 57666, 5000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('14-01-2018 18:52:14', 'dd-mm-yyyy hh24:mi:ss'), 57666, 5000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('20-01-2018 12:19:07', 'dd-mm-yyyy hh24:mi:ss'), 57666, 5000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('24-01-2018 18:38:40', 'dd-mm-yyyy hh24:mi:ss'), 57666, 2990);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('30-01-2018 18:36:01', 'dd-mm-yyyy hh24:mi:ss'), 57666, 1980);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('19-01-2018 18:48:44', 'dd-mm-yyyy hh24:mi:ss'), 57671, 2000);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('19-01-2018 23:41:56', 'dd-mm-yyyy hh24:mi:ss'), 57671, 100);
insert into test2 (yyyymmdd, account_id, vol_eur)
values (to_date('21-01-2018 19:22:51', 'dd-mm-yyyy hh24:mi:ss'), 57671, 5000);
commit;
One option with a recursive cte.
with rownums as (select t.*,row_number() over(partition by id order by dt) as rnum
from tbl t
)
,rsum as (select id,dt,val,rnum,val as cumsum,0 as dt_diff
from rownums
where rnum = 1
union all
select r.id
,r.dt
,r.val
,r.rnum
,case when dt_diff + rs.dt - r.dt > 7 then r.val
when dt_diff + rs.dt - r.dt <= 7 and r.val + rs.cumsum < 1200 then r.val+rs.cumsum
else 0 end
,case when dt_diff + rs.dt - r.dt > 7 then 0
else dt_diff + rs.dt - r.dt end
from rsum rs
join rownums r on r.id = rs.id and r.rnum = rs.rnum+1
)
select id,dt,val,case when cumsum = 0 and lag(cumsum,1) over(partition by id order by dt) <= 1200 then val+lag(cumsum,1) over(partition by id order by dt)
when cumsum = 0 and lag(cumsum,1) over(partition by id order by dt) > 1200 then val
else cumsum end as res
from rsum
order by 1,2
Compute row numbers per user id in the first cte rownums.
Select the first row from the previously defined rownums cte as the anchor row and then iterate through the remaining rows, joining with the anchor row and looking one row ahead at a time. case expression here checks for the conditions.
Cumulative sum was set to 0 by the rsum cte, this indicates a new group starts based on either the sum exceeding 1200 within 7 days or a new 7 day period starting. Use lag to finally compute values on those rows.
Sample Demo in SQL Server

SQL loop inserts

I have a company table with list of companies name and company id.
Now there is a Value table which hold information about the company with reference to company id.
I need to first get the list and size of the companies and for all the companies insert a particular feature information in the Value table.
This means I need to have all companies having those features in the Value table.
I tried to use the below SQL which gives a compilation error. But the for loop works well without the insert.
DECLARE
x NUMBER(2) ;
BEGIN
FOR x IN (select distinct company_num from company where comp_IN_comp='T') LOOP
INSERT INTO VALUE (PROPERTY_NUM, DATA_GROUP, NUM_UPDATES,
CREATED_DATE, CREATED_BY, LAST_UPDATED_DATE, LAST_UPDATED_BY, VALUE) VALUES
('78', x ,'0', TO_DATE('2015-12-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),
'ADMIN', TO_DATE('2015-12-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'ADMIN', 'N');
END LOOP;
END;
You don't need a loop for this - just use an insert-select statement:
INSERT INTO VALUE (PROPERTY_NUM,
DATA_GROUP,
NUM_UPDATES,
CREATED_DATE,
CREATED_BY,
LAST_UPDATED_DATE,
LAST_UPDATED_BY,
VALUE)
SELECT DISTINCT '78',
company_num,
'0',
TO_DATE('2015-12-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),
'ADMIN',
TO_DATE('2015-12-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),
'ADMIN',
'N'
FROM company
WHERE comp_in_comp='T'

Aggregating Data SQL

MachineID Active_Inactive Time
A 0 10.10 am
A 0 10.11 am
A 1 10.12 am
A 0 10.13 am
A 0 10.14 am
A 0 10.15 am
A 1 10.16 am
A 1 10.17 am
A 1 10.18 am
Now, from the above table I want to find out the output in a way that it gives me how many times Machine A was active and how many times inactive in a 2 minute window. So the aggregation needs to be done for every two minute stint. Like A was 2- twice inactive from 10.10- 10.11 and 0 times active. How is the best way to represent the output table
There are 5 slots
10.10-10.11(1), 10.12-10.13(2) and so on...
The output should look something like this..
Slots Active A Inactive A
1 0 2
2 1 1
3 0 2
4 1 1
5 2 0
Assuming that time is a date type, this is the what I would do. Take note that this is on oracle. But it should not differ much.
CREATE TABLE temp (
Machine nvarchar2 (10),
Active number,
dt date
);
INSERT INTO temp VALUES ('A', 0, to_date('10.10 am', 'hh.mi am'));
INSERT INTO temp VALUES ('A', 0, to_date('10.11 am', 'hh.mi am'));
INSERT INTO temp VALUES ('A', 1, to_date('10.12 am', 'hh.mi am'));
INSERT INTO temp VALUES ('A', 0, to_date('10.13 am', 'hh.mi am'));
INSERT INTO temp VALUES ('A', 0, to_date('10.14 am', 'hh.mi am'));
INSERT INTO temp VALUES ('A', 0, to_date('10.15 am', 'hh.mi am'));
INSERT INTO temp VALUES ('A', 1, to_date('10.16 am', 'hh.mi am'));
INSERT INTO temp VALUES ('A', 1, to_date('10.17 am', 'hh.mi am'));
INSERT INTO temp VALUES ('A', 1, to_date('10.18 am', 'hh.mi am'));
Select
Machine,
Active,
to_char(dt, 'hh') || '.' || to_char(floor(to_char(DT, 'mi') /2) * 2) || '-' || to_char(dt, 'hh') || '.' || to_char(floor(to_char(DT, 'mi') /2) * 2 + 1) timeGroup
from temp
group by Machine, Active, to_char(dt, 'hh') || '.' || to_char(floor(to_char(DT, 'mi') /2) * 2) || '-' || to_char(dt, 'hh') || '.' || to_char(floor(to_char(DT, 'mi') /2) * 2 + 1)
;
You can use conversion, string and date functions to create grouping
SELECT machine_id, active_inactive,CONVERT(VARCHAR(13),time,21)+ ':'+RIGHT ('00'+FLOOR(CAST(DATEPART(minute,time)/2) *2 AS VARCHAR(2)),2), COUNT(*)
FROM yourtable
GROUP BY machine_id, active_inactive, CONVERT(VARCHAR(13),time,21)+ ':'+RIGHT ('00'+FLOOR(CAST(DATEPART(minute,time)/2) *2 AS VARCHAR(2)),2)