SQL statement to collect data in a day-by-day, hour-for-hour fashion - sql

I have a database which gets updated with 200-1000 new rows per day. Now, I'd like to have an SQL-statement which returns the data day-by-day, hour-by-hour so I can give a rough estimate for the current trend, i.e. how many rows will be added to the database today, just by taking a quick look at those historical graphs.
So, say that I would like to have 10 graphs printed out for the last 10 days, with the data summed up for every hour, like:
Day9:21,24,15,18,...,30,28,25 : tot 348 (number of rows per hour for day 9 and the total)
Day8:32,37,38,43,...,45,55,65 : tot 442 (number of rows per hour for day 8 and the total)
...
...
Day0:18,25,28,X,Y... : tot 'S' (stats for today so far. What will S be?)
How would the SQL-statement look like to collect the data in this day-by-day, hour-for-hour fashion?
Instead of looking at the graps visually in order to give a rough estimate of today's total 'S', even better would be to compute a prediction of 'S'. But that would be a completely other problem I guess... Any tips for how to do that or hints where I can get more information would be much appreciated!
Thanks,
/Tommy

Hum, depending on your database engine, you'll get different results, but with PostgreSQL, I would do something like that :
SELECT date_trunc('hour', table.date), count(table.id)
FROM table
GROUP BY date_trunc('hour', table.date)
ORDER BY date_trunc('hour', table.date)
The date_trunc function truncates a timestamp field up to a certain point. That query would return you hour by hour, the number of queries, you would just have to do the sums in your software.
If you really mean to have a SQL query returning exactly what you want, I think you'll have to make a function returning a sql set with the proper data, but I think it's easier to do it in your code.

MySQL has a bunch of date/time functions... you might be looking for HOUR(date) as an equivalent to date_trunc('hour', date) in PostGreSQL.
So, if you wanted by Day and by Hour...
SELECT Day(theDate), Hour(theDate), COUNT(1)
FROM theTable
WHERE ....
GROUP BY Day(theDate), Hour(theHour)
ORDER BY Day(theDate), Hour(theHour)
It would give you rows like this:
Day,Hour,Count
1,0,102
1,1,133
...
10,22,47
10,23,384

I had a similar situation, using Oracle. With a table named reporting_data, I wanted a query that could tell me how many records had been inserted per hour, and how many had been inserted in 10 minute increments.
Per hour was easy:
SELECT TO_CHAR(TRUNC(r.creation_date, 'HH'), 'DD-MON-YYYY HH24:MI:SS'),
COUNT (*)
FROM reporting_data r
WHERE r.creation_date > TO_DATE ('27-OCT-2008', 'dd - mon - yyyy')
AND r.creation_date < TO_DATE ('28-OCT-2008', 'dd - mon - yyyy')
GROUP BY TO_CHAR (TRUNC (r.creation_date, 'HH'), 'DD-MON-YYYY HH24:MI:SS')
ORDER BY TO_CHAR (TRUNC (r.creation_date, 'HH'), 'DD-MON-YYYY HH24:MI:SS') ASC
That query would return counts all of the records between Oct 27 and Oct 28, broken down per hour, based on the creation_date column.
Breaking it down in 10 minute increments, instead of hourly increments, was a bit harder, but with some manipulation it was doable.
SELECT SUBSTR(TO_CHAR(r.creation_date, 'DD-MON-YYYY HH24:MI:SS'), 1, 16) || '0:00',
COUNT (*)
FROM reporting_data r
WHERE r.creation_date > TO_DATE ('27-OCT-2008', 'DD-MON-YYYY')
AND r.creation_date < TO_DATE ('28-OCT-2008', 'DD-MON-YYYY')
GROUP BY SUBSTR (TO_CHAR (r.creation_date, 'DD-MON-YYYY HH24:MI:SS'), 1, 16) || '0:00'
There's a lot of string manipulation going on there, so it might not be the most performant way of doing it. On a table of over 25,000,000 rows, it took about a minute to execute. (Then again, just doing a SELECT COUNT(*) on the same table took about 30 seconds, too, so there may have been other issues aside from the query.)

Related

How to Group by Current day and Count Rows?

Hello I have table "os_txn.pay_link" and inside there are many columns.
What I want to do is that I want to count the row numbers by looking at "merchant_id" column for the current day.
So for example what I am looking for an output is that today one of "merchant_id" has
"8" rows. So I want to know the number of rows of the "merchant_id" column for current day.
I think I should use count(*) in view with select statement but couldnt succeed about syntax. So I am open your suggestions thank you.
If I understood you correctly, a simple option would be
select merchant_id, count(*)
from os_txn.pay_link
where date_column = trunc(sysdate)
group by merchant_id;
presuming that date_column contains date only (i.e. for today, 8th of October 2022, that's its value - no hours, minutes or seconds).
If date column contains time component, again - a simple option - would be
select merchant_id, count(*)
from os_txn.pay_link
where trunc(date_column) = trunc(sysdate)
group by merchant_id;
If there's an index on date_column, then such a code wouldn't use it (unless it is a function-based index) so you'd rather modify it to
where date_column >= trunc(sysdate)
and date_column < trunc(sysdate + 1)
If that's not it, do post sample data and desired result.

Discrepancy in counts - Oracle SQL group by query

I am trying to fetch the count of records between 3 PM and 4 PM. The first query returns 473 records whereas the second query returns 474 between 3 PM and 4 PM. Please can you let me know which one could be correct or what I need to do in order to identify the query that provides the accurate result?
select count(*)
from table
where start_ts between
to_timestamp('2017-03-06 15:00:00','YYYY-MM-DD HH24:MI:SS') and to_timestamp('2017-03-06 16:00:00','YYYY-MM-DD HH24:MI:SS')
select count(*),to_char(start_ts,'YYYY-MM-DD HH24')
from table
where start_ts between
to_timestamp('2017-03-06 00:00:00','YYYY-MM-DD HH24:MI:SS') and to_timestamp('2017-03-06 23:59:59','YYYY-MM-DD HH24:MI:SS')
group by to_char(start_ts,'YYYY-MM-DD HH24')
order by to_char(start_ts,'YYYY-MM-DD HH24')
Here is one guess. The first query is return 374 records and the second is returning two rows, one with 373 records and one with 1 record.
The 1 record has a time of exactly '2017-03-06 16:00:00', so it shows up in a different bin from the rest.
This seems like a plausible explanation, although it requires that the numbers be in the other order.

working with a date in SQL

i know this query is not right, and kind of jumbled. but it sort of displays what i want to do. what I'm trying to figure out is how to use the current date in a query. basically i want to subtract a stored date from the current date and if the result is < 30 do something. but i obviously don't know how to work with dates.... i am assuming that it shouldn't be a char value, but if i just use sys date oracle gives me a table error.
select e.STUDENT_ID
from COURSES c, CLASS_ENROLLMENT e, (SELECT TO_CHAR (SYSDATE, 'MM-DD-YYYY') as now
FROM DUAL) t
where t - c.END_DATE <= 30;
Assuming the rest of your query is correct this should solve your date problem:
select e.STUDENT_ID
from COURSES c, CLASS_ENROLLMENT e
where to_date(to_char(sysdate, 'DD-MON-RR')) - c.END_DATE <= 30;
You don't need to select sysdate from dual unless you just want to display it for one reason or another without querying something else. You can just specify it as sysdate as part of a any query anywhere.
The reason I converted it to a character and then to a date in this case is just to remove the time from sysdate, this way it will be 30 days from the given day, regardless of time. If you didn't care about time you could just say sysdate - c.end_date <=30
As an fyi - you probably need to add join conditions between the COURSES and CLASS_ENROLLMENT tables. The above should not result in a sql error and should do you want with respect to the date of the records, but it's unlikely to be what you want (in full).

Oracle SQL WHERE within a time range using sysdate

I'm trying to select data from the previous day, and within a certain time frame, but I may be calculating my where clause incorrectly. I've tried switching times around etc. Basically I want to see all data from 6am-6pm, and then 7pm-3am, but My results aren't relecting such. I've tried between trunc(sysdate)-1 '00:00:00'<- but specifying the time, but I feel I'm not familiar enough with the function.
Note: DB is in UTC hence the 8/24.
Query:
--TOTAL PROBLEM STOW EVENTS
SELECT to_char(entry_date -8/24, 'DD-MON-YYYY HH12:MI:SSam'), OLD_BIN_ID old_bin, NEW_BIN_ID NEW_BIN, ISBN ASIN, QUANTITY
FROM BINEDIT_ENTRIES
WHERE ENTRY_DATE BETWEEN trunc(SYSDATE) -1 +4/24 AND trunc(SYSDATE) -1 +16/24
--where entry_date BETWEEN trunc(sysdate)-1 '00:00:00' AND trunc(sysdate)-1 '00:00:00.000'
AND substr(old_bin_id,1,2) = 'SC'
AND substr(new_bin_id,1,2) = 'vt'
GROUP BY ENTRY_DATE, OLD_BIN_ID, NEW_BIN_ID, ISBN, Quantity
ORDER BY QUANTITY DESC;
Result:
This appears to look correct, BUT when I change to look at other time range, it shows me this..
Second Query(Night Time):
--TOTAL PROBLEM STOW EVENTS
SELECT to_char(entry_date -8/24, 'DD-MON-YYYY HH12:MI:SSam'), OLD_BIN_ID old_bin, NEW_BIN_ID NEW_BIN, ISBN ASIN, QUANTITY
FROM BINEDIT_ENTRIES
WHERE ENTRY_DATE BETWEEN trunc(SYSDATE) -1 +16/24 AND trunc(SYSDATE) -1 +24/24
--where entry_date BETWEEN trunc(sysdate)-1 '00:00:00' AND trunc(sysdate)-1 '00:00:00.000'
AND substr(old_bin_id,1,2) = 'SC'
AND substr(new_bin_id,1,2) = 'vt'
GROUP BY ENTRY_DATE, OLD_BIN_ID, NEW_BIN_ID, ISBN, Quantity
ORDER BY QUANTITY DESC;
Result:
As you can see it doesn't appear to be looking at the where clause, I believe I have it formatted incorrectly, I typically just look at yesterday as a whole, and not a time range, so this is my first time attempting this. Thank you.
Effectively you're asking for everything between 8 AM and 4 PM local time. I say 8 AM since you're adding 16 hours in the WHERE clause and subtracting 8 in the SELECT clause.
If you meant to query between 7 PM local time and 3AM you would just add 8 hours in the WHERE clause:
WHERE ENTRY_DATE BETWEEN
trunc(SYSDATE) -1 +19/24 + 8/24
AND trunc(SYSDATE) -1 +27/24 + 8/24

PLSQL - trunc function - booking due within 24 hours

I was just wondering how would I go about checking to see if, for example, a booking is due within 24 hours?
My bookings table will have the important fields that may help in finding the solution: studiono, title, date, time, hour
At the moment, I have tried the following:
select StudioNo
from Bookings
where sysdate - "DATE" <1
and "TIME" - trunc("Time") + trunc(systimestamp) > systimestamp;
However, I don't think this works. Am I doing this correctly?
Any help is appreciated.
Without knowing what your database structure is:
select StudioNo
from Bookings
where to_date(date || time, 'dd-mon-yyyyhh24:mi:ss') < sysdate +1
and to_date(date || time, 'dd-mon-yyyyhh24:mi:ss') > sysdate
basically, create a single date/time field from your 2 seperate date and time columns (which I'm assuming here are strings), and then compare that to sysdate + 1
Firstly, is there any particular reason why your Bookings table has separate columns for date and time? The Oracle datatype DATE will include both of these in a single column. This will then make the required query much more straight forward:
SELECT StudioNo
FROM Bookings
WHERE BookingDate BETWEEN SYSDATE AND SYSDATE+1;