Combining year and month into a same column - sql

How can I combine year and month into a one column with format YYYYMM? My data doesn't have leading zeros. Below are example columns.
Year
Month
2019
7
2019
10
2020
11
2020
3
2021
1

In most RDBMS platforms, you can CONCAT both values, while using a bit of string manipulation trickery on the Month field to get it to conform to the format by adding a leading 0 in the event of a single-digit month value:
SELECT CONCAT(Year, RIGHT(CONCAT('0', Month), 2) AS YearMonth FROM Dates
YearMonth
201907
201910
202011
202003
202101
db<>fiddle.uk

You can combine them as a number:
year * 100 + month
If you want a string, you can convert this to a string:
cast(year * 100 + month as char(6))

The way you put it, concatenation along with the LPAD function might be what you're looking for. See line #8.
SQL> with test (year, month) as
2 (select 2019, 7 from dual union all
3 select 2019, 10 from dual union all
4 select 2020, 11 from dual union all
5 select 2020, 3 from dual
6 )
7 select year, month,
8 year || lpad(month, 2, '0') result
9 from test;
YEAR MONTH RESULT
---------- ---------- ----------------------------------
2019 7 201907
2019 10 201910
2020 11 202011
2020 3 202003
SQL>

Related

Get count days in current year by day name or day id

name id
----------------
Mon 1
Thu 2
Wen 3
Thr 4
Fri 5
Sat 6
San 7
How get count day where id in eg. (1,2,3,4) and year is 2021
The result should be 208.
Actually, it is 208 for year 2021.
SQL> WITH
2 year AS (SELECT &par_year year FROM DUAL),
3 calendar
4 AS
5 ( SELECT TRUNC (TO_DATE (y.year, 'yyyy'), 'yyyy') + LEVEL - 1 datum
6 FROM year y
7 CONNECT BY LEVEL <=
8 ADD_MONTHS (TRUNC (TO_DATE (y.year, 'yyyy'), 'yyyy'), 12)
9 - TRUNC (TO_DATE (y.year, 'yyyy'), 'yyyy'))
10 SELECT SUM (CASE
11 WHEN TO_NUMBER (TO_CHAR (c.datum, 'd')) IN (1,
12 2,
13 3,
14 4)
15 THEN
16 1
17 ELSE
18 0
19 END) result
20 FROM calendar c;
Enter value for par_year: 2021
RESULT
----------
208
SQL> /
Enter value for par_year: 2020
RESULT
----------
210
SQL>
What does it do?
YEAR CTE contains year you're interested in
CALENDAR CTE creates all dates in that particular year
SUM function conditionally adds 1 if TO_CHAR(datum, 'd') is 1, 2, 3 or 4
that's all

How do I get 1 week data from year 2018 based on 7 days based on this year in oracle?

I am trying to dynamically retrieve data based on dates. For example I want data from 7 days before today and same 7 days from 2020 dynamically.
I tried
SELECT *
FROM table_1
WHERE insert_date > TRUNC(SYSDATE) - 7 or ((insert_date< trunc(sysdate)-365) and (insert_date> trunc(sysdate)-372))
order by insert_date
The problem with this query is if I were to run this query now, this will give me correct data for 2020 and 2021. However if I were to run this same query in 2022, it will give me data from 2022 and 2021 when I want is data based on 2022 and 2020. I was hoping if someone could help me with this issue. I was able to figure out if I want to compare month to month but not week..
Thank you,
Sam
Presume that
today is (yyyy-mm-dd) 2021-04-08 which means that you'd want to return rows whose insert_date is
if you run the query "today", between
2021-04-01 and 2021-04-08
2020-04-01 and 2020-04-08
if you run the query "today next year" (i.e. 2022-04-08)
2022-04-01 and 2022-04-08
2020-04-01 and 2020-04-08
this is contents of your table:
SQL> select * from table_1 order by id;
ID INSERT_DAT Return in
---------- ----------
1 2021-04-08 -- 2021
2 2021-04-03 -- 2021
3 2021-04-02 -- 2021
4 2021-03-31
5 2020-04-05 -- 2021 and 2022
6 2020-04-04 -- 2021 and 2022
7 2020-04-12
8 2022-04-08 -- 2022
9 2022-03-30
9 rows selected.
Query; lines #4 and 5 make sure that query returns rows in year 2020:
SQL> select sysdate from dual;
SYSDATE
----------
2021-04-08
SQL> select a.*
2 from table_1 a
3 where a.insert_date between trunc(sysdate) - 7 and trunc(sysdate)
4 or a.insert_date between add_months(trunc(sysdate), -12 * (extract(year from sysdate) - 2020)) - 7
5 and add_months(trunc(sysdate), -12 * (extract(year from sysdate) - 2020))
6 order by a.insert_date desc;
ID INSERT_DAT
---------- ----------
1 2021-04-08
2 2021-04-03
3 2021-04-02
5 2020-04-05
6 2020-04-04
SQL>
Next year, on 2022-04-08, query would return
SQL> select sysdate from dual;
SYSDATE
----------
2022-04-08
SQL> select a.*
2 from table_1 a
3 where a.insert_date between trunc(sysdate) - 7 and trunc(sysdate)
4 or a.insert_date between add_months(trunc(sysdate), -12 * (extract(year from sysdate) - 2020)) - 7
5 and add_months(trunc(sysdate), -12 * (extract(year from sysdate) - 2020))
6 order by a.insert_date desc;
ID INSERT_DAT
---------- ----------
8 2022-04-08
5 2020-04-05
6 2020-04-04
SQL>
Didn't quite got the requirement. But, assuming you want to take 2020 as a standard date and get 7 days of data from today and the same 7 days from 2020.
I had used the substr to remove the year part and replace it with the standard year. As I had difficulty testing with 2022 date, took 2019 as my standard date.
select distinct cast(to_date(p.insert_date, 'DD-MON-YYYY') as timestamp) as insert_date,
cast(to_date(SYSDATE-7, 'DD-MON-YYYY') as timestamp) as tst_date
from table_1 p
where 1=1 and ( (to_date(p.insert_date, 'DD-MON-YYYY') > to_date(SYSDATE-7, 'DD-MON-YYYY') )
or (to_date(p.insert_date, 'DD-MON-YYYY')> trunc(to_date(substr(to_date(SYSDATE, 'DD-MON-YYYY'),1,7)||'19', 'DD-MON-YYYY')-7)
and to_date(p.insert_date, 'DD-MON-YYYY') <= trunc(to_date(substr(to_date(SYSDATE, 'DD-MON-YYYY'),1,7)||'19', 'DD-MON-YYYY')))
)
order by create_date desc;
-- Standard date for 2020
select substr(to_date(SYSDATE, 'DD-MON-YYYY'),1,7)||'20' from dual;

Query Optimization for my code in Oracle SQL

Here is my code:
select
(case when c.yr = 2019 and c.mon = 10 then 'October 2019'
when c.yr = 2019 and c.mon = 11 then 'November 2019'
when c.yr =2019 and c.mon = 12 then 'December 2019' end) as dae
from (
select substr(d,-4,4) as yr, substr(d,1,2) as mon
from
(select '10/11/2019' as d from dual) )c;
`
So I don't want to hard code the dates for the next 5 years, Is there a function that makes this easier.
Here is the Sample Input I want to try
10/11/2019
11/11/2019
12/11/2019
01/11/2020
Expected Output
October 2019
November 2019
December 2019
January 2020
You could use to_date() to turn your string to a date, and then convert it back to a string in the desired format with to_char():
to_char(to_date(d, 'mm/dd/yyyy'), 'Month yyyy')
Demo on DB Fiddle:
with t as (
select '10/11/2019' d from dual
union all select '11/11/2019' from dual
union all select '12/11/2019' from dual
union all select '01/11/2020' from dual
)
select to_char(to_date(d, 'mm/dd/yyyy'), 'Month yyyy') new_dt from t
| NEW_DT |
| :------------- |
| October 2019 |
| November 2019 |
| December 2019 |
| January 2020 |
Use connect by to generate as many dates as you want. Here the gen_dates CTE starts with your start_date and returns a total of 4 months per your example. To increase the number of months to generate, increase the number 4 to a higher number.
with gen_dates(date_in) as (
select add_months('11-OCT-2019', level -1) date_in
from dual
connect by level <= 4
)
select date_in, to_char(date_in, 'Month yyyy') date_out
from gen_dates;
DATE_IN DATE_OUT
--------- --------------
11-OCT-19 October 2019
11-NOV-19 November 2019
11-DEC-19 December 2019
11-JAN-20 January 2020
4 rows selected.

Calculating holidays: number of saturdays and sundays within the given date range query in Oracle

I want to calculate holidays: the number of Saturdays and Sundays within the given date range query in Oracle.
You could use the ROW GENERATOR technique to first generate the dates for a given range, and then count only the SATURDAYs and SUNDAYs.
For example, this query will give me the total count of saturdays and sundays between 1st Jan 2014 and 31st Dec 2014 -
SQL> WITH DATA AS
2 (SELECT to_date('01/01/2014', 'DD/MM/YYYY') date1,
3 to_date('31/12/2014', 'DD/MM/YYYY') date2
4 FROM dual
5 )
6 SELECT SUM(holiday) holiday_count
7 FROM
8 (SELECT
9 CASE
10 WHEN TO_CHAR(date1+LEVEL-1, 'DY','NLS_DATE_LANGUAGE=AMERICAN') IN ('SAT', 'SUN')
11 THEN 1
12 ELSE 0
13 END holiday
14 FROM data
15 CONNECT BY LEVEL <= date2-date1+1
16 )
17 /
HOLIDAY_COUNT
-------------
104
SQL>

oracle month to day

I have data as below in which data is splitted as below where month 1 represent JAN ,Month 2 represent FEB and so on.
MONTH VALUE
1 93
2 56
3 186
4 60
Now I need to calculate sum of value based on number of days.
Ex- If date is between Jan 1st to March 31st then SUM is 335(93+56+186)
If date is between Jan 17th to March 31st then sum is 287(45+56+186) .
Here 45 for month of january is dervied from average per day for month of JAN (93/31==3) .Multiplied by number of days in January for the required period.
Ignore leap year and FEB month can be taken 28 days always.
As one of the approaches, you can turn a month into a list of days(dates) that constitute it (ease filtering operation), and perform calculation as follows:
/* sample of data that you've provided */
with t1(mnth,val) as(
select 1, 93 from dual union all
select 2, 56 from dual union all
select 3, 186 from dual union all
select 4, 60 from dual
),
/*
Generates current year dates
From January 1st 2014 to December 31st 2014
*/
dates(dt) as(
select trunc(sysdate, 'YEAR') - 1 + level
from dual
connect by extract(year from (trunc(sysdate, 'YEAR') - 1 + level)) <=
extract(year from sysdate)
)
/*
The query that performs calculations based on range of dates
*/
select sum(val / extract(day from last_day(dt))) as result
from dates d
join t1
on (extract(month from d.dt) = t1.mnth)
where dt between date '2014-01-17' and -- January 17th 2014 to
date '2014-03-31' -- March 31st 2014
Result:
RESULT
----------
287