SQL Query to get dates of X days after current date - sql

How can i construct a query that would return some 'x' number of dates after the current date (sysdate)?
For example if today is 18-May-2018 and I ask for x=2, then I should get
19-May-2018
20-May-2018
as the output.

You may use generate_series.
SELECT generate_series(current_date + 1,
current_date + 2,
interval '1' day)
Docs
In plsql, you may set x as variable and then use it in your query.
knayak=# \set x 5
knayak=# SELECT generate_series(current_date + 1,
current_date + :x,
interval '1' day);
generate_series
---------------------------
2018-05-19 00:00:00+05:30
2018-05-20 00:00:00+05:30
2018-05-21 00:00:00+05:30
2018-05-22 00:00:00+05:30
2018-05-23 00:00:00+05:30
You may format the dates in desired format with TO_CHAR
SELECT to_char(dt,'DD-MON-YYYY') as dates
FROM generate_series(current_date + 1,
current_date + 2,
interval '1' day) as dt
dates
-------------
19-MAY-2018
20-MAY-2018

If you're using PostgreSQL, you could use this:
SELECT current_date + s.a AS dates
FROM generate_series(1, 2, 1) AS s(a);
And change 2 to value of your x

since you have written sysdate, I believe you are looking for an oracle database, if you are looking for an oracle database please use the following statement
select trunc(sysdate)+level ldate from dual
connect by level <&x;
above query will ask for x, when you give the value of x as 3, it will generate two days from sysdate

Related

Passing Dynamic Date Part to Date_Add in BigQuery

Is there a way to pass a dynamic string to the date part that comes after the integer in the date_add function?
I.e.
date_add('2023-01-01', interval 7 {dynamic_date_part})
where {dynamic_date_part} could be 'day', 'week', 'month' etc?
I tried this but it rejects anything that gets put there as just "unexpected"
You can use this query to add the dynamic date part:
select date_add(dte, interval n {dynamic_date_part}) as date
from (select current_date as dte, 1 as n union all
SELECT CURRENT_DATE, 2)
As 1 and 2 in
from (select current_date as dte, 1 as n union all
SELECT CURRENT_DATE, 2)
represent the day/week/month of interval.
Here is the query and output:

SQL Oracle How to convert String Week into date

I have dates stored like String in database.
The format is 'yyyy-ww' (example: '2015-43').
I need to get the first day of the week.
I tried to convert this string into date but there is no 'ww' option for the function "to_date".
Do you have an idea to perform this convertion?
EDIT
Test results based on the answers -
Thanks for your anwsers, but I have many problems to apply your solutions to my context:
select
TRUNC ( 2015 + ((43 - 1) * 7), 'IW' )
from dual
==> Error : ORA-01722: invalid number
select
TRUNC(to_date('2015','YYYY')+ to_number('01') *7, 'IW')
from dual
==> 2015-02-02 00:00:00
I waited for a date in january
select
trunc(to_date(regexp_substr('2015-01', '\d+',1,2), 'YYYY') + regexp_substr('2015-01', '\d+') * 7, 'IW') dt2
from dual
==> 0039-09-14 00:00:00
select
regexp_substr('2015-01', '\d+',1,2) as res1,
regexp_substr('2015-01', '\d+') * 7 as res2
from dual
==> res1 = 01
==> res2 = 14105
try to use by truncate
with t as (
select '16-2010' dt from dual
)
--
--
select dt,
trunc(to_date(regexp_substr(dt, '\d+',1,2), 'YYYY') + regexp_substr(dt, '\d+') * 7, 'IW') dt2
from t
I have dates stored like String in database.
You should never do that. It is a bad design. you should store date as DATE and not as a string. For all kinds of requirements for date manipulations Oracle provides the required DATE functions and format models. As and when needed, you could extract/display the way you want.
I need to get the first day of the week.
TRUNC (dt, 'IW') returns the Monday on or before the given date.
Anyway, in your case, you have the literal as YYYY-WW format. You could first extract the year and week number and combine them together to get the date using TRUNC.
TRUNC ( year + ((week_number - 1) * 7)
, 'IW
)
So, the above should give you the Monday of the week number passed for that year.
SQL> WITH DATA AS
2 ( SELECT '2015-43' str FROM dual
3 )
4 SELECT TRUNC(to_date(SUBSTR(str, 1, 4),'YYYY')+ to_number(SUBSTR(str, instr(str, '-',1)+1))*7, 'IW')
5 FROM DATA
6 /
TRUNC(TO_
---------
23-NOV-15
SQL>
Similar to Lalit's, however, I think I've corrected the math (his seemed to be off a bit when I tested .. )
with w_data as (
select sysdate + level +200 d from dual connect by level <= 10
),
w_weeks as (
select d, to_char(d,'yyyy-iw') c
from w_data
)
SELECT d, c, trunc(d,'iw'),
TRUNC(
to_date(SUBSTR(c, 1, 4)||'0101','yyyymmdd')-8+to_char(to_date(SUBSTR(c, 1, 4)||'0101','yyyymmdd'),'d')
+to_number(SUBSTR(c, instr(c, '-',1)+1)-1)*7 ,'IW')
FROM w_weeks;
The extra columns help show the dates before, and after.
I would do the following:
WITH d1 AS (
SELECT '2015-43' AS mydate FROM dual
)
SELECT TRUNC(TRUNC(TO_DATE(REGEXP_SUBSTR(mydate, '^\d{4}'), 'YYYY'), 'YEAR') + (COALESCE(TO_NUMBER(REGEXP_SUBSTR(mydate, '\d+$')), 0)-1) * 7, 'IW')
FROM d1
The first thing the above query does is get the first four digits of the string 2015-43 and truncates that to the closest year (if you convert convert 2015 using TO_DATE() it returns a date within the current month; that is SELECT TO_DATE('2015', 'YYYY') FROM dual returns 01-FEB-2015; we need to truncate this value to the YEAR in order to get 01-JAN-2015). I then add the number of weeks minus one times seven and truncate the whole thing by IW. This returns a date of 01-OCT-2015 (see SQL Fiddle here).
According ISO the 4th of January is always in week 1, so your query should look like
Select
TRUNC(TO_DATE(REGEXP_SUBSTR(your_column, '^\d{4}')||'-01-04', 'YYYY-MM-DD')
+ 7*(REGEXP_SUBSTR(your_column, '\d$')-1), 'IW')
from your_table;
However, there is a problem. ISO year used for Week number can be different than actual year. For example, 1st Jan 2008 was in ISO week number 53 of 2007.
I think a proper working solution you get only when you generate ISO weeks from date value.
WITH w AS
(SELECT TO_CHAR(DATE '2010-01-04' + LEVEL * INTERVAL '7' DAY, 'IYYY-IW') AS week_number,
TRUNC(DATE '2010-01-04' + LEVEL * INTERVAL '7' DAY, 'IW') AS first_day
FROM dual
CONNECT BY DATE '2010-01-04' + LEVEL * INTERVAL '7' DAY < SYSDATE)
SELECT your_Column, first_day
FROM w your_table
JOIN w ON week_number = your_Column;
Your date range must bigger than 2010-01-04 and not bigger than current day.
This is what I used:
select
to_date(substr('2017/01',1,4)||'/'||to_char(to_number(substr('2017/01',6,2)*7)-5),'yyyy/ddd') from dual;

How to use Oracle SQL Date and Time

I have the following example :
select * from my_table
where date between ('19-06-2014 00:00:00,000000000 EUROPE/BUCHAREST') and ('19-06-2014 23:59:59,000000000 EUROPE/BUCHAREST'
If I run this query it returns the correct values . What I need is something like this :
select * from my_table
where date between ('today - 2DAYS ') and ('today - 1DAY')
Do you have any idea how I can achieve this?
Try following solution:
--for one day results
select * from my_table where date between sysdate - 2 and sysdate - 1
--If you wish to start from the beginning of the day:
select * from my_table where date between trunc(sysdate) - 2 and trunc(sysdate) - 1
FYI - sysdate referes the current date and substrating value will be counted in terms of day. If you wish to substract 12 hrs, you should substract 0.5.

dates of past 12 months in oracle

Need a query that lists all the dates of the past 12 months
say my current date is 10-21-2013. need to use sysdate to get the data
The result should look like
10/21/2013
...
10/01/2013
09/30/2013
...
09/01/2013
...
01/31/2013
...
01/01/2013
...
11/30/2012
...
11/01/2012
Please help me with this..
Thanks in advance.
AVG
Allowing for leap years and all, by using add_months to work out the date 12 months ago and thus how many rows to generate ...
select trunc(sysdate) - rownum + 1 the_date
from dual
connect by level <= (trunc(sysdate) - add_months(trunc(sysdate),-12))
You could do something like this:
select to_date('21-oct-2012','dd-mon-yyyy') + rownum -1
from all_objects
where rownum <=
to_date('21-oct-2013','dd-mon-yyyy') - to_date('21-oct-2012','dd-mon-yyyy')+1
of course, you could use parameters for the start and end date to make it more usable.
-or- using sysdate, like this:
select sysdate + interval '-1' year + rownum -1
from all_objects
where rownum <=
sysdate - (sysdate + interval '-1' year)
Try this
SELECT SYSDATE,
SYSDATE-1,
<continue>
SYSDATE-30,
<continue>
.........
<continue>
SYSDATE-364,
SYSDATE-365
FROM DUAL;

Postgresql generate_series of months

I'm trying to generate a series in PostgreSQL with the generate_series function. I need a series of months starting from Jan 2008 until current month + 12 (a year out). I'm using and restricted to PostgreSQL 8.3.14 (so I don't have the timestamp series options in 8.4).
I know how to get a series of days like:
select generate_series(0,365) + date '2008-01-01'
But I am not sure how to do months.
select DATE '2008-01-01' + (interval '1' month * generate_series(0,11))
Edit
If you need to calculate the number dynamically, the following could help:
select DATE '2008-01-01' + (interval '1' month * generate_series(0,month_count::int))
from (
select extract(year from diff) * 12 + extract(month from diff) + 12 as month_count
from (
select age(current_timestamp, TIMESTAMP '2008-01-01 00:00:00') as diff
) td
) t
This calculates the number of months since 2008-01-01 and then adds 12 on top of it.
But I agree with Scott: you should put this into a set returning function, so that you can do something like select * from calc_months(DATE '2008-01-01')
You can interval generate_series like this:
SELECT date '2014-02-01' + interval '1' month * s.a AS date
FROM generate_series(0,3,1) AS s(a);
Which would result in:
date
---------------------
2014-02-01 00:00:00
2014-03-01 00:00:00
2014-04-01 00:00:00
2014-05-01 00:00:00
(4 rows)
You can also join in other tables this way:
SELECT date '2014-02-01' + interval '1' month * s.a AS date, t.date, t.id
FROM generate_series(0,3,1) AS s(a)
LEFT JOIN <other table> t ON t.date=date '2014-02-01' + interval '1' month * s.a;
You can interval generate_series like this:
SELECT TO_CHAR(months, 'YYYY-MM') AS "dateMonth"
FROM generate_series(
'2008-01-01' :: DATE,
'2008-06-01' :: DATE ,
'1 month'
) AS months
Which would result in:
dateMonth
-----------
2008-01
2008-02
2008-03
2008-04
2008-05
2008-06
(6 rows)
Well, if you only need months, you could do:
select extract(month from days)
from(
select generate_series(0,365) + date'2008-01-01' as days
)dates
group by 1
order by 1;
and just parse that into a date string...
But since you know you'll end up with months 1,2,..,12, why not just go with select generate_series(1,12);?
In the generated_series() you can define the step, which is one month in your case. So, dynamically you can define the starting date (i.e. 2008-01-01), the ending date (i.e. 2008-01-01 + 12 months) and the step (i.e. 1 month).
SELECT generate_series('2008-01-01', '2008-01-01'::date + interval '12 month', '1 month')::date AS generated_dates
and you get
1/1/2008
2/1/2008
3/1/2008
4/1/2008
5/1/2008
6/1/2008
7/1/2008
8/1/2008
9/1/2008
10/1/2008
11/1/2008
12/1/2008
1/1/2009