Given 03/09/1982 how can we say it is which week day. In this case it will be Tue.
Is it possible to get in a single query?
SQL> SELECT TO_CHAR(date '1982-03-09', 'DAY') day FROM dual;
DAY
---------
TUESDAY
SQL> SELECT TO_CHAR(date '1982-03-09', 'DY') day FROM dual;
DAY
---
TUE
SQL> SELECT TO_CHAR(date '1982-03-09', 'Dy') day FROM dual;
DAY
---
Tue
(Note that the queries use ANSI date literals, which follow the ISO-8601 date standard and avoid date format ambiguity.)
Nearly ten years late to the party, but I think it's neccessary to enhance #Zohaib 's answer as it's result depend on the language of the client. If you display the week day name to a user, it's absolutely fine, but if your code depends on it, I'd rather control the language like so:
SQL> SELECT TO_CHAR(date '1982-03-09', 'DAY', 'NLS_DATE_LANGUAGE = ENGLISH') day FROM dual;
DAY
---------
TUESDAY
SQL> SELECT TO_CHAR(date '1982-03-09', 'DY', 'NLS_DATE_LANGUAGE = ENGLISH') day FROM dual;
DAY
---
TUE
SQL> SELECT TO_CHAR(date '1982-03-09', 'Dy', 'NLS_DATE_LANGUAGE = ENGLISH') day FROM dual;
DAY
---
Tue
To do this in Oracle sql, I tried like this and it worked for me
SELECT
START_DATE,
CASE WHEN START_DAY = 7 THEN 'SUNDAY'
WHEN START_DAY = 1 THEN 'MONDAY'
WHEN START_DAY = 2 THEN 'TUESDAY'
WHEN START_DAY = 3 THEN 'WEDNESDAY'
WHEN START_DAY = 4 THEN 'THURSDAY'
WHEN START_DAY = 5 THEN 'FRIDAY'
WHEN START_DAY = 6 THEN 'SATURDAY'
END DAY_NAME
FROM
(SELECT
TO_CHAR(T.START_DATE, 'DY') START_DAY,
TO_CHAR(T.START_DATE, 'MM/DD/YYYY') START_DATE
FROM
TABLE T )
Related
I have a database structure as below.
period
month
start_date
1
April
2022-04-01
2
May
2022-05-07
3
June
2022-06-04
4
July
2022-07-02
5
August
2022-08-06
6
September
2022-09-03
7
October
2022-10-01
8
November
2022-11-05
9
December
2022-12-03
10
January
2023-01-01
11
February
2023-02-04
12
March
2023-03-04
End date of the year is 2023-03-31.
Based on current_date, how do I select the query to return where the current date falls under Period 6.
My current query as below.
SELECT period FROM table1 as a
WHERE
a.start_date = (SELECT MAX(start_date) FROM table1 as b WHERE
b.start_date <=current_date) and ROWNUM <= 1
Is there anyway to improve the current query which to avoid using subquery?
Today is September 22nd, so - would this do?
Some sample data:
SQL> with test (period, month, start_date) as
2 (select 1, 'april' , date '2022-04-01' from dual union all
3 select 5, 'august' , date '2022-08-06' from dual union all
4 select 6, 'september', date '2022-09-03' from dual union all
5 select 7, 'october' , date '2022-10-01' from dual union all
6 select 10, 'january' , date '2023-01-01' from dual union all
7 select 12, 'march' , date '2023-03-04' from dual
8 ),
Query begins here:
9 temp as
10 (select period, month, start_date,
11 row_number() over (order by start_date desc) rn
12 from test
13 where start_date <= sysdate
14 )
15 select period
16 from temp
17 where rn = 1
18 /
PERIOD
----------
6
SQL>
It still uses a subquery (or a CTE, as in my example), but - as opposed to your approach, it selects from the source table only once, so performance should be improved.
A few more tests: instead of sysdate (line #13), presume that today is September 2nd (which means that it is in period #5):
9 temp as
10 (select period, month, start_date,
11 row_number() over (order by start_date desc) rn
12 from test
13 where start_date <= date '2022-09-02'
14 )
15 select period
16 from temp
17 where rn = 1;
PERIOD
----------
5
SQL>
Or, if today were August 7th:
9 temp as
10 (select period, month, start_date,
11 row_number() over (order by start_date desc) rn
12 from test
13 where start_date <= date '2022-08-07'
14 )
15 select period
16 from temp
17 where rn = 1;
PERIOD
----------
5
SQL>
Your rule for the start_date appears to be:
If the month is January (first month of the calendar year) or April (typically, first month of the financial year) then use the 1st of that month;
Otherwise use the 1st Saturday of the month.
If that is the case then you can calculate the start date of the next month and use the query:
SELECT *
FROM table1
WHERE start_date <= SYSDATE
AND SYSDATE < CASE
WHEN EXTRACT(MONTH FROM ADD_MONTHS(start_date, 1))
IN (1, 4) -- 1st month of calendar or financial year
THEN TRUNC(ADD_MONTHS(start_date, 1), 'MM')
ELSE NEXT_DAY(TRUNC(ADD_MONTHS(start_date, 1), 'MM') - 1, 'SATURDAY')
END
Then, for your sample data:
CREATE TABLE table1 (
period NUMBER(2,0),
month VARCHAR2(9)
GENERATED ALWAYS AS (
CAST(
TO_CHAR(start_date, 'FXMonth', 'NLS_DATE_LANGUAGE=English')
AS VARCHAR2(9)
)
),
start_date DATE
);
INSERT INTO table1 (period, start_date)
SELECT LEVEL,
CASE
WHEN EXTRACT(MONTH FROM ADD_MONTHS(DATE '2022-04-01', LEVEL - 1))
IN (1, 4) -- 1st month of calendar or financial year
THEN ADD_MONTHS(DATE '2022-04-01', LEVEL - 1)
ELSE NEXT_DAY(ADD_MONTHS(DATE '2022-04-01', LEVEL - 1) - 1, 'SATURDAY')
END
FROM DUAL
CONNECT BY LEVEL <= 12;
Outputs:
PERIOD
MONTH
START_DATE
6
September
2022-09-03 00:00:00
fiddle
I have a query to return first Sunday of current month. However, if first Sunday fall on the first day of the month, it gets the next Sunday instead. How could get rid of it to return the first Sunday that on the first day of the month?
Take 1 Aug, 2021 as an example,below query returns second Sunday, 8 Aug 2021.
SELECT TO_CHAR(NEXT_DAY(TRUNC(TO_DATE(('20210801'), 'yyyyMMdd'), 'MM'), 'Sunday'), 'yyyyMMdd') AS FIRST_SUNDAY FROM DUAL;
Move one day back, to the last day of previous month:
SQL> SELECT TO_CHAR (
2 NEXT_DAY (TRUNC (TO_DATE (('20210801'), 'yyyyMMdd'), 'MM') - 1,
3 'sunday'), -- ^^
4 'yyyyMMdd') AS FIRST_SUNDAY --> this
5 FROM DUAL;
FIRST_SU
--------
20210801
SQL> SELECT TO_CHAR (
2 NEXT_DAY (TRUNC (TO_DATE (('20210701'), 'yyyyMMdd'), 'MM') - 1,
3 'sunday'),
4 'yyyyMMdd') AS FIRST_SUNDAY
5 FROM DUAL;
FIRST_SU
--------
20210704
SQL>
How can i return data from 2 days ago at 11:00:00 PM to all of yesterday ending at 11:59:59 PM?
I currently have only yesterdays date query:
SELECT *
FROM table
WHERE code = '00'
AND to_char(RQST_TMSTMP, 'yyyy-mm-dd') = to_char(sysdate-1, 'yyyy-mm-dd')
How about
select *
from table
where code = '00'
and rqst_tmstmp >= trunc(sysdate - 2) + 11/24
and rqst_tmstmp <= trunc(sysdate);
Here's what all those TRUNCs represent (so that you could follow what's going on):
SQL> select sysdate, -- today, right now
2 trunc(sysdate) ts, -- today at midnight
3 trunc(sysdate - 2) ts_2, -- 2 days ago at midnight
4 trunc(sysdate - 2) + 11/24 ts_2_11 -- 2 days ago at midnight + 11 hours
5 from dual;
SYSDATE TS TS_2 TS_2_11
---------------- ---------------- ---------------- ----------------
29.11.2018 17:07 29.11.2018 00:00 27.11.2018 00:00 27.11.2018 11:00
SQL>
If the column is capturing hours & minutes then use,
TO_CHAR(RQST_TMSTMP,'DD-MM-YY HH24:MI')
I wanna roll six months dates starting from 2016 to current date, output should be like below
Year Start_Date End_Date
2016 1/1/2016 30/6/2016
2016 1/7/2016 31/12/2016
2017 ... like this for 2017 & 2018
I tried like fetch first date of the year like
SELECT TRUNC(to_date(Date_key, 'YYYYMMDD'), 'YEAR')
FROM Table;
and adding six months from first date, but in this case end date will be problem. Is there a function I can do this without loop?
Something like this?
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> select extract (year from add_months (date '2016-01-01', (level - 1) * 6)) year,
2 add_months (date '2016-01-01', (level - 1) * 6) start_date,
3 add_months (date '2016-01-01', (level) * 6) - 1 end_date
4 from dual
5 connect by level <= (extract (year from sysdate) - 2016 + 1) * 2;
YEAR START_DATE END_DATE
---------- ---------- ----------
2016 01.01.2016 30.06.2016
2016 01.07.2016 31.12.2016
2017 01.01.2017 30.06.2017
2017 01.07.2017 31.12.2017
2018 01.01.2018 30.06.2018
2018 01.07.2018 31.12.2018
6 rows selected.
SQL>
You can also try this,
SELECT :p_from_year + CEIL(ROWNUM/2)-1,
ADD_MONTHS(TRUNC(TO_DATE(:p_from_year + CEIL(rownum/2)-1, 'YYYY'), 'YYYY'),6-(MOD(rownum, 2)*6)) from_date,
ADD_MONTHS(TRUNC(TO_DATE(:p_from_year + CEIL(rownum/2)-1, 'YYYY'), 'YYYY'),12-(MOD(rownum, 2)*6))-1 to_date
FROM dual
CONNECT BY CEIL(rownum/2)-1 <= (:p_to_year - :p_from_year)
Is this the best way to determine if an Oracle date is on a weekend?
select * from mytable
where
TO_CHAR (my_date, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') IN ('SAT', 'SUN');
As of Oracle 11g, yes. The only viable region agnostic alternative that I've seen is as follows:
SELECT *
FROM mytable
WHERE MOD(TO_CHAR(my_date, 'J'), 7) + 1 IN (6, 7);
Not an answer to the question. But some more information. There are many more SQL tricks with date.
to_char(sysdate, 'd') --- day of a week, 1,2,3 .. to 7
to_char(sysdate, 'dd') --- day of a month, 1,2,3 .. to 30 or 31
to_char(sysdate, 'ddd') --- day of a year, 1,2,3 .. to 365 or 366
to_char(sysdate, 'w') --- week of a month, 1,2,3,4 or 5
to_char(sysdate, 'ww') --- week of a year, 1,2,3 .. to 52
More here: to_char function.
MOD(TO_CHAR(my_date, 'J'), 7) + 1 IN (6, 7)
is NOT correct!
The day number of weekend days may be 6 & 7, or 7 and 1, depending on the NLS-settings.
So the PROPER test (irrespective of NLS-settings) is this one mentioned before:
TO_CHAR (my_date, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') IN ('SAT', 'SUN')
In my opinion the best option is
TO_CHAR (my_date, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') IN ('SAT', 'SUN')
set NLS_TERRITORY before
alter session set NLS_TERRITORY=SWEDEN;
So you are sure which numbers are weekends