Selecting record count by month - sql

I have to get a count of transaction by each for a year Oct 2020 to Oct 2021 . The following is the query for the over all year . Is there a way I can do this count by each month with out having to run 12 times this query?
select count(*)
from Transaction_Details
where date_created between TO_DATE('2020-10-01 01:00:00','YYYY-MM-DD hh24:mi:ss')
and TO_DATE('2021-10-01 01:00:00','YYYY-MM-DD hh24:mi:ss');

Truncate the date to the start of the calendar month and GROUP BY that:
select TRUNC(date_created, 'MM') As calendar_month_start,
count(*)
from Transaction_Details
where date_created between DATE '2020-10-01' + INTERVAL '1' HOUR
and DATE '2021-10-01' + INTERVAL '1' HOUR
GROUP BY
TRUNC(date_created, 'MM')
ORDER BY
calendar_month_start;
If you want it starting at 1am on the 1st of each month then:
select TRUNC(date_created - INTERVAL '1' HOUR, 'MM')
+ INTERVAL '1' HOUR AS month_from_1am_on_1st,
count(*)
from Transaction_Details
where date_created between DATE '2020-10-01' + INTERVAL '1' HOUR
and DATE '2021-10-01' + INTERVAL '1' HOUR
GROUP BY
TRUNC(date_created - INTERVAL '1' HOUR, 'MM')
ORDER BY
month_from_1am_on_1st;
db<>fiddle here

Related

Get data of last Month day by day in oracle sql

I want to get data from last month day by day, I can get the last 30 days but I just want the month as it may be less or more than 30 days,
this is the query for getting the last 30 days
SELECT Trunc(timestamp),
Count(*)
FROM table1
WHERE Trunc(timestamp) > Trunc(sysdate - 30)
GROUP BY Trunc(timestamp)
ORDER BY 1;
Also, I am using it in a shell script if I can make a variable in the script and put it the query
To get data from the start of the current month until today:
SELECT TRUNC(timestamp) AS day,
COUNT(*)
FROM table1
WHERE timestamp >= TRUNC(SYSDATE, 'MM')
AND timestamp < TRUNC(SYSDATE) + INTERVAL '1' DAY
GROUP BY TRUNC(timestamp)
ORDER BY day
To get data from the same day last month until today:
SELECT TRUNC(timestamp) AS day,
COUNT(*)
FROM table1
WHERE timestamp >= ADD_MONTHS(TRUNC(SYSDATE), -1)
AND timestamp < TRUNC(SYSDATE) + INTERVAL '1' DAY
GROUP BY TRUNC(timestamp)
ORDER BY day
db<>fiddle here

Select Data From Multiple Days Between Certain Times (Spanning 2 days)

I need to know how many entries appear in my DB for the past 7 days with a timestamp between 23:00 & 01:00...
The Issue I have is the timestamp goes across 2 days and unsure if this is even possible in the one query.
So far I have come up with the below:
select trunc(timestamp) as DTE, extract(hour from timestamp) as HR, count(COLUMN) as Total
from TABLE
where trunc(timestamp) >= '12-NOV-19' and
extract(hour from timestamp) in ('23','00','01')
group by trunc(timestamp), extract(hour from timestamp)
order by 1,2 desc;
The result I am hoping for is something like this:
DTE | Total
20-NOV-19 5
19-NOV-19 4
18-NOV-19 4
17-NOV-19 6
Many thanks
Filter on the day first comparing it to TRUNC( SYSDATE ) - INTERVAL '7' DAY and then consider the hours by comparing the timestamp to itself truncated back to midnight with an offset of a number of hours.
select trunc(timestamp) as DTE,
extract(hour from timestamp) as HR,
count(COLUMN) as Total
from TABLE
WHERE timestamp >= TRUNC( SYSDATE ) - INTERVAL '7' DAY
AND ( timestamp <= TRUNC( timestamp ) + INTERVAL '01:00' HOUR TO MINUTE
OR timestamp >= TRUNC( timestamp ) + INTERVAL '23:00' HOUR TO MINUTE
)
group by trunc(timestamp), extract(hour from timestamp)
order by DTE, HR desc;
Subtract or add an hour to derive the date. I'm not sure what date you want to assign to each period, but the idea is:
select trunc(timestamp - interval '1' hour) as DTE,
count(*) as Total
from t
where trunc(timestamp - interval '1' hour) >= DATE '2019-11-12' and
extract(hour from timestamp) in (23, 0)
group by trunc(timestamp - interval '1' hour)
order by 1 desc;
Note: If you want times between 11:00 p.m. and 1:00 a.m., then you want the hour to be 23 or 0.

data of last 4 quarter

I want to fetch data of last 4 quarter including current quarter.
Suppose if I run the query on 30-MAR-2019 then I want data from 01-APR-2018 to 31-MAR-2019
and if I run the query on 01-apr-2019 then I want data between 01-JUL-2018 and 30-JUN-2019
Could you please help me on the same
The tricky part is getting the last day of the quarter.
This solution calculates the starting day of the range by subtracting 9 months from the target date and then truncating with the 'Q' mask which gives us the first day of the quarter. We then calculate that date again, subtract one day then add twelve months and that gives the last day of the current quarter:
with tgt as ( select date '2019-03-30' as dt from dual
union all select date '2019-02-28' as dt from dual
union all select date '2019-04-01' as dt from dual
)
select trunc(tgt.dt - interval '9' month, 'Q') as range_st,
(trunc(tgt.dt - interval '9' month, 'Q') - 1) + interval '12' month as range_end
from tgt
/
There may be a slicker solution out there, but this is the end of my coffee break :)
this will work:
select TRUNC(sysdate+1, 'Q') - interval '9' month,TRUNC(sysdate+1, 'Q') +
interval '3' month -1
from dual ;
01-JUL-2018 30-JUN-2019
select TRUNC(to_date('30-MAR-2019')+1, 'Q') - interval '9'
month,TRUNC(to_date('30-MAR-2019')+1, 'Q') + interval '3' month -1
from dual ;
01-APR-2018 31-MAR-2019
This is dynamically:
With param as (
Select
to_date(extract(year from add_months(sysdate,-12)) ||
lpad((floor(extract(month from add_months(sysdate,-12))/3)*3)+1,2, '0') || '01',
'yyyymmdd') first_date
from dual
)
Select
level quartal,
Add_months(first_date, ((level-1)*3)) from_dat,
Last_day(add_months(first_date, ((level-1)*3)+3)-1) to_dat
From param
connect by level <= 4;
You can do:
select (trunc(sysdate, 'Q') + interval '3' month) as next_quarter_start,
(trunc(sysdate, 'Q') + interval '15' month) - interval '1' day as next_quarter_end
from dual;

Teradata Interval function

Teradata fails while using in-built function, INTERVAL, when used with MONTH specification for deriving dates on February month
SELECT Cast('2017-12-29' as date) - INTERVAL '10' MONTH;
SELECT Cast('2017-12-30' as date) - INTERVAL '10' MONTH;
SELECT Cast('2017-12-31' as date) - INTERVAL '10' MONTH;
SELECT Cast('2018-12-29' as date) - INTERVAL '10' MONTH;
SELECT Cast('2018-12-30' as date) - INTERVAL '10' MONTH;
SELECT Cast('2018-12-31' as date) - INTERVAL '10' MONTH;
SELECT Cast('2019-12-29' as date) - INTERVAL '10' MONTH;
SELECT Cast('2019-12-30' as date) - INTERVAL '10' MONTH;
SELECT Cast('2019-12-31' as date) - INTERVAL '10' MONTH;
SELECT Cast('2020-12-30' as date) - INTERVAL '10' MONTH;
SELECT Cast('2020-12-31' as date) - INTERVAL '10' MONTH;
or
SELECT CURRENT_DATE - INTERVAL '10' MONTH;-- << If current date is 29,30,31 day of December month Non leap year and 30,31 day of December month leap year>>
Use Add_Months function instead of Interval function..
SELECT ADD_MONTHS(CAST ('2017-12-29' AS DATE),-10);
SELECT ADD_MONTHS(CURRENT_DATE,-10); -- << If current date is 29,30,31 day of December month Non leap year and 30,31 day of December month leap year>>

update table with dates with month

There's a table dates_calendar:
id | date
-------------------------
13 | 2016-10-23 00:00:00
14 | 2016-10-24 00:00:00
I need to update this table and insert dates until the next month counting from the last date in the table. E.g. last date is 2016-10-24 00:00:00 - I need to insert dates till 2016-10-31. After that (the last date now is 2016-10-31) next statement call should insert dates till 2016-11-30 and so on.
Example of my SQL code, but it inserts 30 days all the time.
INSERT INTO dates_calendar (date)
VALUES (
generate_series(
(SELECT date FROM dates_calendar ORDER BY date DESC LIMIT 1) + interval '1 day',
(SELECT date FROM dates_calendar ORDER BY date DESC LIMIT 1) + interval '1 month',
'1 day'
)
);
I'm using PostgreSQL. As well would be fine to get rid of a duplicated SELECT statement of the last date.
insert into dates_calendar (date)
select dates::date
from (
select max(date)::date+ 1 next_day, '1day'::interval one_day, '1month'::interval one_month
from dates_calendar
) s,
generate_series(
next_day,
date_trunc('month', next_day)+ one_month- one_day,
one_day) dates;
To calculate the first and last date you need to insert you can use this query:
select max(date) + interval '1' day as first_day,
date_trunc('month', max(date) + interval '1' month) - interval '1' day as last_day
from dates_calendar
The expression date_trunc('month', max(date) + interval '1' month) calculates the start date of the next month. Subtracting one day from that will give you the last day of that month.
This can then be used to generate the list of dates:
with from_to (first_day, last_day) as (
select max(date) + interval '1' day,
date_trunc('month', max(date) + interval '1' month) - interval '1' day
from dates_calendar
)
select dt
from generate_series( (select first_day from from_to), (select last_day from from_to), interval '1' day) as t(dt);
And finally this can be used to insert the generated rows into the table:
with from_to (first_day, last_day) as (
select max(date) + interval '1' day,
date_trunc('month', max(date) + interval '1' month) - interval '1' day
from dates_calendar
)
insert into dates_calendar (date)
select dt
from generate_series( (select first_day from from_to), (select last_day from from_to), interval '1' day) as t(dt);
with max_date (d) as (select max(date)::date from dates_calendar)
insert into dates_calendar (date)
select d
from generate_series (
(select d from max_date) + 1,
(select date_trunc('month', d + interval '1 month')::date - 1 from max_date),
'1 day'
) g(d)