Query to show per week, per day, per hour - sql

I'm working in PLSQL, trying to find event counts for a given week, broken down by day and hour.
Essentially I want to plug in the week and then have the count of events such that I can easily discern counts >1M per day AND 300k per hour (=GOLD), 500k per day and 200k per hour (silver), 100k per day 30k per hour.
I'm trying something like this to get data per day, but I'm not sure how to break it down per day, per hour. Oracle rookie here.
SELECT TO_CHAR(TRUNC(store.transaction_datetime, 'HH'), 'DD-MON-YYYY HH24:MI:SS'), Identifier,
COUNT (*)
FROM data.stats store
WHERE store.transaction_datetime >= '2016-09-04 00:00:00'
AND store.transaction_datetime <= '2016-09-10 23:59:59'
GROUP BY Identifier, TO_CHAR (TRUNC (store.transaction_datetime, 'HH'), 'DD-MON-YYYY HH24:MI:SS')
ORDER BY TO_CHAR (TRUNC (store.transaction_datetime, 'HH'), 'DD-MON-YYYY HH24:MI:SS') ASC;
anything I can throw into excel and perform counts will work for me
any help appreciated

Let me know if it helps:
SELECT T.*,
CASE WHEN CNT_PER_DAY > ... AND CNT_PER_HOUR > ... THEN 'GOLD'
WHEN CNT_PER_DAY > ... AND CNT_PER_HOUR > ... THEN 'SILVER'
WHEN CNT_PER_DAY > ... AND CNT_PER_HOUR > ... 'BRONZE'
ELSE ...
END CATEGORY
FROM (
SELECT DISTINCT
Identifier,
TO_CHAR(TRUNC(store.transaction_datetime, 'HH'), 'DD-MON-YYYY HH24:MI:SS') HOUR_TIME,
COUNT (*) OVER (PARTITION BY Identifier,TRUNC(store.transaction_datetime, 'HH')) CNT_PER_HOUR,
TO_CHAR(TRUNC(store.transaction_datetime, 'DD'), 'DD-MON-YYYY HH24:MI:SS') DAY_TIME,
COUNT (*) OVER (PARTITION BY Identifier,TRUNC(store.transaction_datetime, 'DD')) CNT_PER_DAY,
store.transaction_datetime
FROM data.stats store
WHERE store.transaction_datetime >= '2016-09-04 00:00:00'
AND store.transaction_datetime <= '2016-09-10 23:59:59') T
ORDER BY TO_CHAR (TRUNC (T.transaction_datetime, 'HH'), 'DD-MON-YYYY HH24:MI:SS') ASC;

Related

Trying to group a query to display day event by hours

I'm trying to get an account of a daily count from an Oracle query to display count by hours from 14:00 to 19:00. I'm using this query. I want to group the count output.
Select count(*), extract(hour from eventtime) as hours
from TR_MFS_LOADCARRIER
WHERE eventid = 5
And eventtime BETWEEN to_date('05/09/2022 14:00:00', 'dd/mm/yyyy hh24:mi:ss')
and to_date('05/09/2022 19:00:00', 'dd/mm/yyyy hh24:mi:ss')
group by hours
It fails where am I going wrong.
The hours alias is defined in the SELECT clause after the GROUP BY clause is evaluated so it cannot be used in the GROUP BY clause; use EXTRACT(hour from eventtime) instead.
Select count(*),
extract(hour from eventtime) as hours
from TR_MFS_LOADCARRIER
WHERE eventid = 5
And eventtime BETWEEN to_date('05/09/2022 14:00:00', 'dd/mm/yyyy hh24:mi:ss')
and to_date('05/09/2022 19:00:00', 'dd/mm/yyyy hh24:mi:ss')
group by extract(hour from eventtime)
If your eventtime column is a DATE data-type then you cannot EXTRACT the hours field and need to cast it to a TIMESTAMP data-type:
Select count(*),
extract(hour from CAST(eventtime AS TIMESTAMP)) as hours
from TR_MFS_LOADCARRIER
WHERE eventid = 5
And eventtime BETWEEN to_date('05/09/2022 14:00:00', 'dd/mm/yyyy hh24:mi:ss')
and to_date('05/09/2022 19:00:00', 'dd/mm/yyyy hh24:mi:ss')
group by extract(hour from CAST(eventtime AS TIMESTAMP))
fiddle

SUM records by hour + add subqueries

So i've got this code:
SELECT to_char(dstamp, 'HH24') as HOUR, SUM(update_qty) total_received
FROM inventory_transaction
WHERE dstamp BETWEEN to_date('28/05/2021 18:00:00', 'dd/mm/yyyy hh24:mi:ss')
AND to_date('29/05/2021 06:00:00', 'dd/mm/yyyy hh24:mi:ss')
AND code = 'Receipt'
GROUP BY to_char(dstamp, 'HH24')
ORDER BY HOUR ASC ;
Im trying to add an additional column to it, thats gonna be showing me total_putaway, so exactly the same query, but code = 'Putaway'. I was trying to do it by the CROSS JOIN, or some subqueries but it doesent really work, as i want to group my records by hour so 12 rows in total.
Use conditional aggregation:
SELECT to_char(dstamp, 'HH24') as HOUR,
SUM(CASE WHEN code = 'Receipt' THEN update_qty END) as total_received,
SUM(CASE WHEN code = 'Putaway' THEN update_qty END) as total_putaway
FROM inventory_transaction
WHERE dstamp BETWEEN to_date('28/05/2021 18:00:00', 'dd/mm/yyyy hh24:mi:ss') AND
to_date('29/05/2021 06:00:00', 'dd/mm/yyyy hh24:mi:ss')
GROUP BY to_char(dstamp, 'HH24')
ORDER BY HOUR ASC

How to get data on minute base instead of hourly base?

I use the following query to get my data counted on hourly base:
select to_char(trunc(time, 'HH'), 'DD/MM/YY HH24') as "date",
count(event), count(distinct id) from source
where time >= date '2021-01-01'
group by trunc(time,'HH')
order by trunc(time,'HH');
What I now want to do is the same but on minute base. How can I get this done?
To me, you could have avoided trunc entirely as you use TO_CHAR anyway:
select to_char(time, 'dd/mm/yy hh24') ...
If you want to include minutes, no problem:
select to_char(time, 'dd/mm/yy hh24:mi') as "date",
count(event), count(distinct id)
from source
where ...
group by to_char(time, 'dd/mm/yy hh24:mi')
Note that sorting by strings probably won't produce desired results. Perhaps, if you'd change date format to e.g. 'yyyymmdd hh24:mi'

Fetch data from Oracle Database on hourly and daily basis using timestamp and current date

I have written query to get data for a particular day, but need a query to get the data on hourly and daily basis
My Query:
SELECT
TRAN_USERTRANSACTIONS.APPLICATIONNUMBER
FROM
TRAN_USERTRANSACTION
WHERE TRAN_USERTRANSACTIONS.CREATEDAT
LIKE '%19-09-19%'
GROUP BY
TRAN_USERGTRANSACTION.APPLICATIONNUMBER;
CREATEDAT is Timestampin in format as follows :DD-MM-YY hh.mm.ss.ssss AM/PM
By hour(hope this helps):
Select TRAN_USERTRANSACTIONS.APPLICATIONNUMBER
, TO_CHAR(TRAN_USERTRANSACTIONS.CREATEDAT ,'HH AM')
from TRAN_USERTRANSACTION
WHERE TRAN_USERTRANSACTIONS.CREATEDAT LIKE '%19-09-19%'
group by TRAN_USERTRANSACTIONS.APPLICATIONNUMBER
, TO_CHAR(TRAN_USERTRANSACTIONS.CREATEDAT ,'HH AM')
order by TO_CHAR(dat_azu,'HH AM') asc;
I assume you want a summary by hour and not by application. If so, the hour should be in the GROUP BY:
SELECT TO_CHAR(t.CREATEDAT, 'YYYY-MM-DD HH24') as dh,
COUNT(*)
FROM TRAN_USERTRANSACTION t
WHERE t.CREATEDAT >= DATE '2019-09-19' AND
t.CREATEDAT < DATE '2019-09-20'
GROUP BY TO_CHAR(t.CREATEDAT, 'YYYY-MM-DD HH24')
ORDER BY dh;

Oracle Set operator query

Have a SQL query on Oracle 11g which returns the count of whether a record having certain ID and status exists within +/- 15 minutes range in a table.
Now I wish to ignore the current date by adding a condition like AND TIMESTAMP < trunc(sysdate).
However, for cases where the record exists in todays date I wish to ignore the date comparison check in the query '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
SELECT count(1) AS COUNT
FROM MASTER_ONE
WHERE ID='123' AND STATUS= 'ACTIVE'
AND '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
UNION ALL
SELECT count(1) AS COUNT
FROM MASTER_TWO
WHERE ID='321' AND STATUS= 'ACTIVE'
AND '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
How do I do this?
The first problem with your query is that you're doing a string comparison on the date. Use to_date instead of to_char and let Oracle help you out.
SELECT
to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') AS orig_date
, to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') - 1 / 24 / 4 AS fifteen_min_prior
, to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') + 1 / 24 / 4 AS fifteen_min_after
FROM dual;
Output:
ORIG_DATE FIFTEEN_MIN_PRIOR FIFTEEN_MIN_AFTER
------------------------- ------------------------- -------------------------
20-JUL-10 07:15:11 PM 20-JUL-10 07:00:11 PM 20-JUL-10 07:30:11 PM
Then use can use those dates in a BETWEEN condition in the predicate. See Oracle date "Between" Query.
I'm not quite clear what you mean by "However, for cases where the record exists in todays date I wish to ignore the date comparison check in the query." You'd just written that you want to exclude values from the current day. Either you're excluding today's records or you're not.
Ok, you can try something like this, if I understood you correctly:
SELECT count(1) AS COUNT
FROM MASTER_ONE
WHERE ID='123' AND STATUS= 'ACTIVE'
AND (timestamp > trunc(sysdate)
OR (timestamp < trunc(sysdate)
AND timestamp BETWEEN to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') - (1/1440*15)
AND to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') + (1/1440*15)))
UNION ALL
SELECT count(1) AS COUNT
FROM MASTER_TWO
WHERE ID='321' AND STATUS= 'ACTIVE'
AND (timestamp > trunc(sysdate)
OR (timestamp < trunc(sysdate)
AND timestamp BETWEEN to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') - (1/1440*15)
AND to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') + (1/1440*15)))
In this Select, you only apply the 15 minutes condition if your timestamp column has a date prior to sysdate.