Getting extra days from generrate_series - sql

I have the following command
select generate_series('2019-09-01'::timestamp, least(current_date, '2019-09-18'), interval '1 week')
which returns me back
2019-09-01 00:00:00
2019-09-08 00:00:00
2019-09-15 00:00:00
Is it possible to get last result as well even id doesn't fit specified interval?
So I'd like to get back
2019-09-01 00:00:00
2019-09-08 00:00:00
2019-09-15 00:00:00
2019-09-18 00:00:00

Well you could union with that final date:
select generate_series('2019-09-01'::timestamp, least(current_date, '2019-09-18'), interval '1 week')
union
select '2019-09-18'::date;
Should your generate series happen to also include the final date, the union would remove one of the two duplicates. Otherwise, the union would include this final date.

Apply greatest() in the subquery, and then least() in the main query :
select least(date, '2019-09-18') as "Date Interval"
from
(
select
generate_series('2019-09-01'::timestamp,
greatest(current_date, '2019-09-18'),
interval '1 week') as date ) q
Demo

Related

How to display in sql records of past Month (not last 30 days) and update them every 2nd calendar date of the next month?

I am trying to represent data for the past MONTH so for example 30 days from April 2nd and continue to update data every month so that on May 2nd, data shows for the 30 days prior to May 2nd.
I will show my current code:
SELECT 'Working Equipment' label, count(*) FROM LOGS_HISTORY
WHERE MODE__ = 'Working'
AND TIME_ >= add_months(sysdate, -1)
union all
SELECT 'Standby Equipment' label, count(distinct TAG_IDENTIFIER) FROM LOGS_HISTORY
WHERE MODE__ = 'Standby'
AND TIME_ >= add_months(sysdate, -1)
It shows data 30 days prior to sysdate, please look through it and advise what should I change?
For your requirement you can use this:
AND TIME_ >= add_months(trunc(sysdate-1,'MM'),-1)
This example query shows how the start date changes from 1st March to 1st April on 2nd May:
with dates as
( select trunc(date '2022-04-27')+rownum d
from dual
connect by level < 10
)
select d as sys_date, add_months(trunc(d-1,'MM'),-1) from_date
from dates
order by 1;
Result:
SYS_DATE FROM_DATE
-------- ---------
28-APR-2022 00:00:00 01-MAR-2022 00:00:00
29-APR-2022 00:00:00 01-MAR-2022 00:00:00
30-APR-2022 00:00:00 01-MAR-2022 00:00:00
01-MAY-2022 00:00:00 01-MAR-2022 00:00:00
02-MAY-2022 00:00:00 01-APR-2022 00:00:00
03-MAY-2022 00:00:00 01-APR-2022 00:00:00
04-MAY-2022 00:00:00 01-APR-2022 00:00:00
05-MAY-2022 00:00:00 01-APR-2022 00:00:00
06-MAY-2022 00:00:00 01-APR-2022 00:00:00

How to fill the time gap after grouping date record for months in postgres

I have table records as -
date n_count
2020-02-19 00:00:00 4
2020-07-14 00:00:00 1
2020-07-17 00:00:00 1
2020-07-30 00:00:00 2
2020-08-03 00:00:00 1
2020-08-04 00:00:00 2
2020-08-25 00:00:00 2
2020-09-23 00:00:00 2
2020-09-30 00:00:00 3
2020-10-01 00:00:00 11
2020-10-05 00:00:00 12
2020-10-19 00:00:00 1
2020-10-20 00:00:00 1
2020-10-22 00:00:00 1
2020-11-02 00:00:00 376
2020-11-04 00:00:00 72
2020-11-11 00:00:00 1
I want to be grouped all the records into months for finding month total count which is working, but there is a missing of month. how to fill this gap.
time month_count
"2020-02-01" 4
"2020-07-01" 4
"2020-08-01" 5
"2020-09-01" 5
"2020-10-01" 26
"2020-11-01" 449
This is what I have tried.
SELECT (date_trunc('month', date))::date AS time,
sum(n_count) as month_count
FROM table1
group by time
order by time asc
You can use generate_series() to generate all starts of months between the earliest and latest date available in the table, then bring the table with a left join:
select d.dt, coalesce(sum(t.n_count), 0) as month_count
from (
select generate_series(date_trunc('month', min(date)), date_trunc('month', max(date)), '1 month') as dt
from table1
) as d(dt)
left join table1 t on t.date >= d.dt and t.date < d.dt + interval '1 month'
group by d.dt
order by d.dt
I would simply UNION a date series, generated from MIN and MAX date:
demo:db<>fiddle
WITH cte AS ( -- 1
SELECT
*,
date_trunc('month', date)::date AS time
FROM
t
)
SELECT
time,
SUM(n_count) as month_count --3
FROM (
SELECT
time,
n_count
FROM cte
UNION
SELECT -- 2
generate_series(
(SELECT MIN(time) FROM cte),
(SELECT MAX(time) FROM cte),
interval '1 month'
)::date,
0
) s
GROUP BY time
ORDER BY time
Use CTE to calculate date_trunc only once. Could be left out if you like to call your table twice in the UNION below
Generate monthly date series from MIN to MAX date containing your n_count value = 0. Add it to the table
Do your calculation

SQL MONTH AVERGE

Here is what I got to get the duration of the two.
select (TO_TIMESTAMP(s.END, 'hh24:mi:ss') - TO_TIMESTAMP(s.START, 'hh24:mi:ss')) from SESSION s;
I am trying to get the average per month. I do have a time dimension that I can refer to using month_name from the table. However, how to I do this? I have tried to use add_months by casting it but got no luck.
Thank you guys.
VARCHAR for all.
DATE START END RESULT OF QUERY AVERAGE PER MONTH
13-FEB-11 16:00:00 18:00:00 +00 02:00:00.000000 ?
02-APR-11 08:30:00 10:30:00 +00 02:00:00.000000
02-APR-11 16:00:00 18:00:00 +00 02:00:00.000000
05-APR-11 08:30:00 10:30:00 +00 02:00:00.000000
05-APR-11 16:00:00 18:00:00 +00 02:00:00.000000
I would suggest turning the scripts to dates instead of timestamps. This gives you a numeric result that represents the interval as days, which, unlike an interval, you can average.
If you want the average session duration per month, you can aggregate like so:
select
trunc(to_date(s.date, 'dd-mon-yy'), 'mm') mnt,
avg(to_date(s.end, 'hh24:mi:ss') - to_date(t.start, 'hh24:mi:ss')) avg_duration
from session s
group by trunc(to_date(s.date, 'dd-mon-yy'), 'mm')
If you want the result as an interval, you can use numtodsinterval() on the results of the computation:
select
trunc(to_date(s.date, 'dd-mon-yy'), 'mm') mnt,
numtodsinterval(
avg(to_date(s.end, 'hh24:mi:ss') - to_date(t.start, 'hh24:mi:ss')),
'day'
) avg_interval
from session s
group by trunc(to_date(s.date, 'dd-mon-yy'), 'mm')

Filter By date with format 'dd/mm'

I have difficulty in syntax query dbms oracle for filtering by date, but i just want filter by date with format (dd/mm). and my data database record is (dd/mm/yyyy). How query to filter by date mm/dd
tablename.fieldname >= '01/01'
with s as (
select date '2019-01-01' + level * 15 dt from dual connect by level <= 20)
select s.*
from s
where to_number(to_char(dt, 'mmdd')) > 0501;
DT
-------------------
2019-05-16 00:00:00
2019-05-31 00:00:00
2019-06-15 00:00:00
2019-06-30 00:00:00
2019-07-15 00:00:00
2019-07-30 00:00:00
2019-08-14 00:00:00
2019-08-29 00:00:00
2019-09-13 00:00:00
2019-09-28 00:00:00
2019-10-13 00:00:00
2019-10-28 00:00:00
12 rows selected.
Have you tried something like this? Though it's not exactly the format you wanted
SELECT * from yourTableName
WHERE EXTRACT(month from yourDateColumn) >= '1'
AND EXTRACT(day from yourDateColumn) >= '1';
Oracle EXTRACT documentaion
Possible related questions:
Compare only day and month with date field in mysql
SQL Filter Out Specific Month, Day, and Time for Any Year

Running query against quarter or week of the year

I have this query that works for 1 quarter. However, what if I want to do the same query but for 2nd, 3rd, and 4th quarter of the calendar year or even WEEKLY?
How can I do the same query without having to manually change the values defining the quarter or week of the year?
SELECT count(1), AVG(resolved_at::TIMESTAMP - created_at::TIMESTAMP)
FROM supp_cases
WHERE created_at::TIMESTAMP >= '2017-01-01 00:00:00'::TIMESTAMP
AND resolved_at::TIMESTAMP <= '2017-03-31 23:59:59'::TIMESTAMP;
Q1 = 2017-01-01 00:00:00 TO 2017-03-31 23:59:59
Q2 = 2017-04-01 00:00:00 TO 2017-06-30 23:59:59
Q3 = 2017-07-01 00:00:00 TO 2017-09-30 23:59:59
Q4 = 2017-10-01 00:00:00 TO 2017-12-31 23:59:59
How about this?
SELECT TO_CHAR(created_at, 'YYYY-Q') as created_at_yyyyq,
TO_CHAR(resolved_at, 'YYYY-Q') as resolved_at_yyyyq,
count(*)
FROM supp_cases
GROUP BY created_at_yyyyq, resolved_at_yyyyq
ORDER BY created_at_yyyyq, resolved_at_yyyyq;
If you really want rows created and resolved in the same quarter, you can add:
WHERE TO_CHAR(created_at, 'YYYY-Q') = TO_CHAR(resolved_at, 'YYYY-Q')
You might try using intervals, e.g.:
SELECT * FROM example WHERE created_at > '2017-01-01'
AND resolved_at < (DATE('2017-01-01') + INTERVAL '1 WEEKS');
SELECT * FROM example WHERE created_at > '2017-01-01'
AND resolved_at < (DATE('2017-01-01') + INTERVAL '2 MONTHS');