SQL loop inserts - sql

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'

Related

What is the equivalent of SPLIT-APPLY-COMBINE in PostgreSQL

TLDR;
What is the equivalent of the following Python code snippet in PostgreSQL?
df.groupby('column').apply(function)
Where df is a Pandas DataFrame instance.
Context
I am used to the Split-Apply-Combine Paradigm in Python and want to apply the same framework in PostgreSQL.
Suppose I have the following table with a time, place, and measurement:
CREATE TABLE IF NOT EXISTS test_table (place VARCHAR(10), time TIMESTAMP, measurement FLOAT);
TRUNCATE test_table;
INSERT INTO test_table
VALUES ('A', TO_TIMESTAMP('2022-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1.0),
('A', TO_TIMESTAMP('2022-01-01 00:15:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('A', TO_TIMESTAMP('2022-01-01 00:30:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('A', TO_TIMESTAMP('2022-01-01 00:45:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('A', TO_TIMESTAMP('2022-01-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0),
('B', TO_TIMESTAMP('2022-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0),
('B', TO_TIMESTAMP('2022-01-01 00:15:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('B', TO_TIMESTAMP('2022-01-01 00:30:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('B', TO_TIMESTAMP('2022-01-01 00:45:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('B', TO_TIMESTAMP('2022-01-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0),
('C', TO_TIMESTAMP('2022-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1.0),
('C', TO_TIMESTAMP('2022-01-01 00:15:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('C', TO_TIMESTAMP('2022-01-01 00:30:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('C', TO_TIMESTAMP('2022-01-01 00:45:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('C', TO_TIMESTAMP('2022-01-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0);
Associated to each place is a timeseries. Sometimes the measurement device at a given place will flatline and my goal is to move the flatline rows to another table.
I have written the following query to get the table I want for a given place.
SELECT place, time, measurement
FROM (SELECT place, time, measurement, LEAD(measurement, 1) OVER (ORDER BY time) AS leading_measurement
FROM test_table WHERE place = 'A') q
WHERE NOT measurement = leading_measurement OR leading_measurement IS NULL;
Within the query I had a subquery with a clause WHERE place = 'A' because the cleaning algorithm would detect the last row of A as being the same as the first row of B and I would not want to remove that row. But this also means I have not "cleaned" the other two places.
In theory I would like to GROUP BY place run the query, and union the results. However the GROUP BY clause only supports aggregate functions and my query returns multiple rows. I want to somehow SELECT DISTINCT(place) and run a for loop over that list. The Python equivalent is:
test_table.groupby('place') \
.apply(lambda place:
place[place["measurement"].diff(1) != 0])
I can (and have) been using Python to export to CSV then import the CSV into PSQL tables but my boss would greatly appreciate it done in PostgreSQL.
I would appreciate any guidence, even a link to a relevant manual page.
Do not give up on SQL quite so quickly.
If I understand correctly you want to to copy to another table then delete those rows which have the same measurement by place and time. So for Place A move then delete the rows with times 00:30:00 and 00:40:00. This is because those are the same as time stamp 00:15:00. With similar copy and delete for Place B and Place C.
If this is correct then it is quite easily done in SQL, at least Postgres SQL. It can be done in a single statement. Postgres SQL permits DML operations is a CTE. This allows you write a CTE to identify the rows to process in the first table, then use that CTE to insert those rows onto the second table, and finally use the same CTE to delete from the first table. (See demo)
with to_move(rctid) as
( select ctid
from (select place, time, measurement
, lead(measurement, 1) over (partition by place order by time) as leading_measurement, ctid
from test_table
) q
where measurement = leading_measurement
)
, movers as
( insert into test_table_flat (place, time, measurement)
select t.place, t.time, t.measurement
from test_table t
where t.ctid in (select rctid from to_move)
)
delete
from test_table
where ctid in (select rctid from to_move) ;

In Oracle SQL developer how do you insert date and time

I am Unable to insert date data and time data into oracle table. Please find the below query and error
INSERT INTO Sunday_Service (
Service_ID,
Service_date,
Start_time,
End_time,
Service_location,
No_of_children)
Values (
Seq_service_id.nextVal,
TO_DATE('YYYY-MM-DD', '2022-07-03'),
TO_DATE('hh24:mi:ss', '09:00:00'),
TO_DATE('hh24:mi:ss', '10:15:00'),
'RM 2101',
'10');
error:
Error report ORA-01821
You have your parameters switched in your TO_DATE function calls. Your TO_DATE function calls should look like this:
TO_DATE ('2022-07-03', 'YYYY-MM-DD'),
TO_DATE ('09:00:00', 'hh24:mi:ss'),
TO_DATE ('10:15:00', 'hh24:mi:ss')
You have the arguments to to_date() the wrong way around:
INSERT INTO Sunday_Service (Service_ID, Service_date,
Start_time, End_time,
Service_location, No_of_children)
VALUES (Seq_service_id.nextVal,
TO_DATE('2022-07-03', 'YYYY-MM-DD'),
TO_DATE('09:00:00', 'hh24:mi:ss'),
TO_DATE('10:15:00', 'hh24:mi:ss'),
'RM 2101',
'10');
But you probably want to combine the time and date, rather than holding them in separate columns; so if you removed service_date from your table you could do:
INSERT INTO Sunday_Service (Service_ID,
Start_time, End_time,
Service_location, No_of_children)
VALUES (Seq_service_id.nextVal,
TO_DATE('2022-07-03 09:00:00', 'YYYY-MM-DD HH24:MI:SS'),
TO_DATE('2022-07-03 10:15:00', 'YYYY-MM-DD HH24:MI:SS'),
'RM 2101',
'10');
Apart from anything else, that will make it possible to handle service calls that span midnight or multiple days.
You could also use timestamp literals:
...
VALUES (Seq_service_id.nextVal,
TIMESTAMP '2022-07-03 09:00:00',
TIMESTAMP '2022-07-03 10:15:00',
...
or slightly more explcitly:
...
VALUES (Seq_service_id.nextVal,
CAST(TIMESTAMP '2022-07-03 09:00:00' AS DATE),
CAST(TIMESTAMP '2022-07-03 10:15:00' AS DATE),
...
If no_of_children is a number column, as it appears, then the last value should be a number - 10 rather than '10'.

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

Select users who don't have projects assigned in specific date, Oracle SQL

I have 3 tables: Projects, Employees and Assignments. Employees are assigned to different projects and projects can take some time. I need to find an employee who will be free on a specific day (won't have a project assigned).
CREATE TABLE Employee (
id NUMBER(10) NOT NULL PRIMARY KEY,
name VARCHAR2(50) NOT NULL
);
CREATE TABLE Projects (
id NUMBER(10) NOT NULL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL
);
INSERT INTO
Employee(id, name) VALUES (1, 'Joe Doe');
INSERT INTO
Employee(id, name) VALUES (2, 'Alex Doe');
INSERT INTO
Projects(id, name, start_date, end_date)
VALUES (1, 'AAA',
TO_DATE('2020/12/30 00:00:00', 'yyyy/mm/dd hh24:mi:ss'),
TO_DATE('2021/06/30 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
INSERT INTO
Projects(id, name, start_date, end_date)
VALUES (2, 'BBB',
TO_DATE('2020/11/30 00:00:00', 'yyyy/mm/dd hh24:mi:ss'),
TO_DATE('2021/03/30 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
INSERT INTO
Projects(id, name, start_date, end_date)
VALUES (3, 'CCC',
TO_DATE('2020/11/10 00:00:00', 'yyyy/mm/dd hh24:mi:ss'),
TO_DATE('2020/11/30 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
CREATE TABLE Assignments (
id NUMBER(10) NOT NULL PRIMARY KEY,
employee_id NUMBER(10) NOT NULL,
project_id NUMBER(10) NOT NULL,
CONSTRAINT employee_fk FOREIGN KEY (employee_id) REFERENCES Employee(id),
CONSTRAINT project_fk FOREIGN KEY (project_id) REFERENCES Projects(id)
);
INSERT INTO Assignments(id, project_id, employee_id)
VALUES (1, 1, 1);
INSERT INTO Assignments(id, project_id, employee_id)
VALUES (2, 1, 2);
INSERT INTO Assignments(id, project_id, employee_id)
VALUES (3, 2, 1);
INSERT INTO Assignments(id, project_id, employee_id)
VALUES (4, 3, 1);
I know how to check people and their projects, but I need help with month and day condition. Let's say this specific day is 24th of March. I came up with something like this, but it's not what I want - because I guess I need somehow check if a free day is not in project duration time - am I right? How to do this?
SELECT Employee.name, Projects.name
FROM Assignments
INNER JOIN Employee ON Employee.id = Assignments.employee_id
INNER JOIN Projects ON Projects.id = Assignments.project_id
WHERE EXTRACT(month FROM Projects.start_date) < 3 AND
EXTRACT(day FROM Projects.start_date) > 24
GROUP BY Employee.name, Projects.name;
http://sqlfiddle.com/#!4/f483d/4
You can use the DATE literal to create the date and check if the employee is free on the specific date using the EXISTS as follows:
SELECT DISTINCT Employee.name FROM Assignments
INNER JOIN Employee ON Employee.id = Assignments.employee_id
WHERE NOT EXISTS (SELECT 1 FROM Projects
WHERE Projects.id = Assignments.project_id
AND DATE '2020-03-24'
BETWEEN Projects.START_date AND Projects.end_date);
SQL Fiddle
You can also use GROUP BY and HAVING as follows:
SELECT Employee.name FROM Assignments
INNER JOIN Employee ON Employee.id = Assignments.employee_id
INNER JOIN Projects ON Projects.id = Assignments.project_id
GROUP BY Employee.name
HAVING COUNT (CASE WHEN DATE '2020-03-24'
BETWEEN Projects.START_date
AND Projects.end_date
THEN 1 END) = 0
SQL Fiddle

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;