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;
Related
I am looking to obtain all data in a table from yesterday in SQL Oracle.
This is simply enough using the WHERE clause, i.e,
SELECT *
FROM My_Data
WHERE TO_DATE(My_Data.Date,'YYYY-MM-DD') = TRUNC(SYSDATE)-1
However if I now need to add more logic where if the day of the query is a Monday (SYSDATE) then obtain data between Friday and Sunday.
Using a between statement is no issue, I'm just not sure if I can include in a where statement given I'm unable to use case statement here.
Thanks
SELECT
*
FROM
My_Data
WHERE
TO_DATE(My_Data.Date,'YYYY-MM-DD')
Between Case When To_Char(SYSDATE, 'DY') = 'MON' Then TRUNC(SYSDATE)-3 ELSE TRUNC(SYSDATE)-1 END
And TRUNC(SYSDATE)-1
You can use the Case expression in Where clause. Regards...
Don't use TO_DATE on a column that is already a date (and if it is a string then don't store dates as strings).
So you are not dependent on the date language session parameter, you can compare the date to the start of the ISO week (which is independent of language) and you can compare on a date range so that Oracle can use an index on your date column:
SELECT *
FROM My_Data
WHERE "DATE" < TRUNC(SYSDATE)
AND "DATE" >= CASE TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW')
WHEN 0 -- Monday
THEN TRUNC(SYSDATE) - 3
ELSE TRUNC(SYSDATE) - 1
END;
or:
SELECT *
FROM My_Data
WHERE "DATE" < TRUNC(SYSDATE)
AND ( ( TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW') = 0 AND "DATE" >= TRUNC(SYSDATE) - 3 )
OR "DATE" >= TRUNC(SYSDATE) - 1
);
I have an SQL query where I'm trying to select only records from the past two weeks of the present day i.e. using the 'created_on' column. Any ideas how that is done? I know I can't use specific dates because present day is always changing.
select un.id
, t.type_name as type
, un.content_id
, un.app_link
, un.notification_text
, t.id as type_id
, un.seen_yn,un.created_on
, to_char(un.created_on,'YYYY-MM-DD: HH24:MI') as timestamp
from app.user_notifications as un
left join ref.types as t on t.id = un.notification_type
where un.active_yn = true
and un.user_id = 1
and un.seen_yn = false order by un.created_on desc
You can compare the created_on column with an expression that calculates "two weeks before today":
un.created_on >= current_date - interval '2 weeks'
alternatively you can also subtract 14 days
un.created_on >= current_date - 14
Add yet another condition, e.g.
... and un.created_on >= trunc(sysdate) - 14
In Oracle, when you subtract number from a DATE datatype value, you subtract that many days so - subtracting 14 is two weeks back.
SQL> select sysdate right_now,
2 trunc(sysdate) today_midnight,
3 trunc(sysdate) - 14 two_weeks_back
4 from dual;
RIGHT_NOW TODAY_MIDNIGHT TWO_WEEKS_BACK
------------------- ------------------- -------------------
22.03.2022 07:12:54 22.03.2022 00:00:00 08.03.2022 00:00:00
SQL>
Alternatively, if you prefer interval (which actually says what you're doing), then
SQL> select trunc(sysdate) - interval '14' day from dual;
TRUNC(SYSDATE)-INTE
-------------------
08.03.2022 00:00:00
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
My question is similar to following question:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:14582643282111
The difference is my inner query returns two records and I have outer query.
I need to write inner query something like this which will give me a list of dates between two date ranges (I am trying this query whcih does not execute).
Select * from outerTable where my_date in
(
select to_date(r.REQ_DATE) + rownum -1
from all_objects, (MY_INNER_QUERY Where ID =100) r
where rownum <= to_date(r.DUE_DATE,'dd-mon-yyyy')-to_date(r.REQ_DATE,'dd-mon-yyyy')+1;
)
My inner query returns following 2 rows:
Select * from innerTable Where ID =100
Start date end date
3/19/2013 3/21/2013
3/8/2013 3/8/2013
So I am need inner query which will return following dates to outer query:
3/19/2013
3/20/2013
3/21/2013
3/8/2013
Great question - this one really drew me in! The answer was more or less buried further down on Tom's post. Here's the short version, using a table called TestDR to define the ranges. First the TestDR contents:
SELECT * FROM TestDR;
STARTDATE ENDDATE
--------- ---------
19-MAR-13 21-MAR-13
08-MAR-13 08-MAR-13
Now for the query to create one row for each date in the range:
WITH NUMS AS (
SELECT LEVEL-1 DaysToAdd
FROM DUAL
CONNECT BY LEVEL <= 60
)
SELECT StartDate + DaysToAdd TheDate
FROM TestDR
CROSS JOIN NUMS
WHERE TestDR.EndDate - TestDR.StartDate + 1 > DaysToAdd
ORDER BY 1
THEDATE
---------
08-MAR-13
19-MAR-13
20-MAR-13
21-MAR-13
With the query adapted from Tom's posting, you have to know the maximum range going in to "seed" the NUMS query. He used 60 in his example so that's what I used above. If you don't think any row from your subquery will ever have a range of more than 60 days then this will do the trick. If you think the maximum could be as much as 1000 days (about three years) then change the 60 to 1000. I tried this and queried a 2 1/2 year range and the results were instantaneous.
If you want to specify the exact "seed" count you can calculate it if you're willing to make the query a bit more complicated. Here's how I can do it with my TestDR table:
WITH NUMS AS (
SELECT LEVEL-1 DaysToAdd
FROM DUAL
CONNECT BY LEVEL <= (
SELECT MAX(EndDate - StartDate + 1)
FROM TestDR)
)
SELECT ... and the rest of the query as above
For your problem, you don't need to enumerate the dates. A simple JOIN suffices.
SELECT o.*
FROM outerTable o
INNER JOIN innerTable i
ON i.ID = 100
AND o.my_date BETWEEN i.REQ_DT and i.DUE_DT
From your code, I can tell that you must be a OO programmer and not familiar with SQL. It does a lot for you, so don't try to control it. It will hinder it's optimization features.
Don't take this in the wrong way, I had the same mindset (believing that I am smarter than the machine).
In your outer query use an OR statement, which allows your date to be equal to either the return Start_Date or End_Date
AND (date = subQuery.Start_Date
OR date = subQuery.End_Date)
Using your dates:
SELECT smth... FROM some_tab
WHERE your_date IN
( -- remove unnecessary columns, leave only what you select in outer query
-- or select *
SELECT start_date
, TRUNC(start_date, 'iw') wk_starts
, TRUNC(start_date, 'iw') + 7 - 1/86400 wk_ends
, TO_NUMBER (TO_CHAR (start_date, 'IW')) ISO_wk#
FROM
(
SELECT (start_date-1) + LEVEL AS start_date
FROM
( -- replace this part with selecting your start and end dates from your table --
SELECT to_date('03/21/2013', 'MM/DD/YYYY') end_date
, to_date('03/19/2013', 'MM/DD/YYYY') start_date
FROM dual
)
CONNECT BY LEVEL <= (end_date - start_date)
)
) -- your outer query ends --
/
START_DATE WK_STARTS WK_ENDS ISO_WK#
----------------------------------------------------------
3/19/2013 3/18/2013 3/24/2013 11:59:59 PM 12
3/20/2013 3/18/2013 3/24/2013 11:59:59 PM 12
Annual table of dates and ISO weeks etc... Use any dates for start and end dates. The connect by and number of days between is used to generate table on the fly. You may use between operator if using hard structures...:
SELECT start_date
, TRUNC(start_date, 'iw') wk_starts
, TRUNC(start_date, 'iw') + 7 - 1/86400 wk_ends
, TO_NUMBER (TO_CHAR (start_date, 'IW')) ISO_wk#
FROM
(-- This part simplifies above formatting and optional --
SELECT (start_date-1) + LEVEL AS start_date
FROM
(-- Replace start/end dated with any dates --
SELECT TRUNC(ADD_MONTHS (SYSDATE, 12), 'Y')-1 end_date
, TRUNC(SYSDATE, 'YEAR') start_date
FROM dual
)
CONNECT BY LEVEL <= (end_date - start_date) -- number of days between dates
)
/
START_DATE WK_STARTS WK_ENDS ISO_WK#
-----------------------------------------------------------
1/1/2013 12/31/2012 1/6/2013 11:59:59 PM 1
1/2/2013 12/31/2012 1/6/2013 11:59:59 PM 1
1/3/2013 12/31/2012 1/6/2013 11:59:59 PM 1
...
12/28/2013 12/23/2013 12/29/2013 11:59:59 PM 52
12/29/2013 12/23/2013 12/29/2013 11:59:59 PM 52
12/30/2013 12/30/2013 1/5/2014 11:59:59 PM 1
I want to write a query where it displays data between 01-April-2010 to lastday-april-2011.
But I don't want to hard code the year. It should take from system date so it only displays records from this year april to next year april.
Thanks in advance for the help.
select add_months( trunc(sysdate,'YYYY'), -12 )
+ interval '4' month
+ level
- 1
from dual
connect by level <= ( (trunc(sysdate,'YYYY')
+ interval '4' month) -
(add_months( trunc( sysdate, 'YYYY' ), -12 )
+ interval '4' month) )
should work. You could probably simplify the expression that computes the number of rows but I'd have to think for a few minutes about leap years.
If the date column has no time component:
select ...
from mytable
where datecol between add_months(trunc(sysdate,'YYYY'),3)
and add_months(trunc(sysdate,'YYYY'),16)-1
If the date column has a time component:
select ...
from mytable
where datecol >= add_months(trunc(sysdate,'YYYY'),3)
and datecol < add_months(trunc(sysdate,'YYYY'),16)
Your query should be something like this
SELECT *
FROM youtable
WHERE datecolumn BETWEEN to_char(sysdate,'yyyy')+'0401' AND to_char(sysdate,'yyyy')+'0430'