Set first week of the year from the first day of the year until the following monday - sql

I want that Oracle treats weeks the following way:
-The week starts on monday
-The first week of the year is from the first day of the year until the following monday
So for 2015 would be
01-jan-2015 (Thursday) would be 1
02-jan-2015 (Friday) would be 1
03-jan-2015 (Saturday) would be 1
04-jan-2015 (Sunday) would be 1
05-jan-2015 (Monday) would be 2
06-jan-2015 (Tuesday) would be 2
For 2017 would be
01-jan-2017 (Sunday) would be 1
02-jan-2017 (Monday) would be 2
03-jan-2017 (Tuesday) would be 2
04-jan-2017 (Wednesday) would be 2
and so on....
I need the numeration for the year so would go to 1 to 53-54

A little bit of arithmetics will probably do the trick (assuming d is your date):
select TRUNC((case to_char(d, 'DY')
when 'MON' then 6
when 'TUE' then 5
when 'WED' then 4
when 'THU' then 3
when 'FRI' then 2
when 'SAT' then 1
when 'SUN' then 0
end + to_number(to_char(d, 'DDD'))-1) / 7)+1
from v;
The case statement will build an offset according to the day of week
next I add the day of year
then I divide the result by 7 for the week number (starting at 0)
finally, the +1 will start numbering weeks at 1
Please take some time to experiment with it http://sqlfiddle.com/#!4/d41d8/38236 to check if I didn't make a stupid mistake as I didn't have time to test it thoughtfully. Sorry about that...

Use the ISO week date standard: 'iw'.
2014-01-01 was Wednesday actually, so:
select
to_number(to_char(date'2014-01-05', 'iw')) as weeknum,
to_char(date'2014-01-05', 'Day') as day
from dual;
WEEKNUM DAY
----------- ---------
1 Sunday
select
to_number(to_char(date'2014-01-06', 'iw')) as weeknum,
to_char(date'2014-01-06', 'Day') as day
from dual;
WEEKNUM DAY
----------- ---------
2 Monday

Related

SQL - POSTGRES - DATE_PART why is sql resulting in week 53 when it should be week 2

TABLE
INSERT INTO runners
("runner_id", "registration_date")
VALUES
(1, '2021-01-01'),
(2, '2021-01-03'),
(3, '2021-01-08'),
(4, '2021-01-15');
SQL Query
SELECT
DATE_PART('WEEK', R.registration_date) AS week_num,
COUNT(runner_id)
FROM
pizza_runner.runners R
GROUP BY
week_num
ORDER BY
week_num ASC;
I was expecting the query to return weeks 1 and 2 only but for some reason I am getting 53
]1
I was expecting the query to return weeks 1 and 2 only but for some reason I am getting 53
The documentation does a good job explaining the ISO rules for weeks - which Postgres follows:
The number of the ISO 8601 week-numbering week of the year. By definition, ISO weeks start on Mondays and the first week of a year contains January 4 of that year. In other words, the first Thursday of a year is in week 1 of that year.
Using your dataset:
SELECT r.*,
extract(week from registration_date) AS week_num,
extract(isodow from registration_date) as day_of_week
FROM runners r
ORDER BY registration_date;
runner_id
registration_date
week_num
day_of_week
1
2021-01-01
53
5
2
2021-01-03
53
7
3
2021-01-08
1
5
4
2021-01-15
2
5
It turns out that January 3rd, 2021 was a Sunday (day of week 7). January 4st, 2021 was a Monday, and according to the ISO rules this is when the first week of that year began. Previous dates (January 3rd, 2nd, 1st, and so on) belong to the last week of 2020 (week 53), although the dates belong to year 2021.

How to calculate the number of days of first week of the month in SAS.if we consider Saturday as first week day

I am using intnx function.
date1=intnx('qtr',"01APR2021"d,0,'b');
I am thinking of following algo-
1.Check if last month's last day is not Friday.
2.Calculate the number of days till Friday appears(Current Month).
Can anyone help me with this?
Use INTNX to compute the 1st of the month, and then WEEKDAY of that to compute the number of days in the first week.
WEEKDAY function results are
1st-want 1st_want-v2
1 Sunday 1 2
2 Monday 2 3
3 Tuesday 3 4
4 Wednesday 4 5
5 Thursday 5 6
6 Friday 6 7
7 Saturday 7 1
Depending on what you want, (suppose the 1st is a Saturday, do you want 1 or 7 for your result?) For 1, you will need to perform additional calculations.
Example:
Presume if first is a Saturday you want 7 days in first week result.
data have;
call streaminit (2021);
do _n_ = 0 to 23;
date = intnx('month', '01-jan-2019'd, _n_) + rand('integer', 27);
output;
end;
format date date11.;
run;
data want;
set have;
month_1st = intnx('month', date, 0);
sas_weekday_1st = weekday(month_1st);
result = sas_weekday_1st;
result_v2 = mod(sas_weekday_1st,7) + 1;
format month_1st date11.;
run;
Find the first of the month (INTNX() or MDY())
Find the first friday (day=6) of the month (NWKDOM())
Subtract
Assume month and year are provided.
data want;
year = 2020;
month = 1;
start_date = mdy(month, 1, year);
first_friday = nwkdwom(1, 6, month, year);
length_week = start_date - first_friday + 1;
*Toms correction:;
length_week2 = day(nwkdom(1,6,month(date),year(date));
run;
Sounds like you want to know the date of the first Friday in the month. And hence the day of the month of the first Friday in the month.
So let's start with a dataset that has a month that starts on each day of the week.
data example;
input date :date9.;
format date date9.;
dow = weekday(date);
downame=put(date,downame.-l);
cards;
01OCT2000
01MAY2000
01FEB2000
01MAR2000
01JUN2000
01SEP2000
01JAN2000
;
Now we can use the INTNX() function with the WEEK interval to find the date of the first Friday. We could then use the DAY() function to find the day of the month for that Friday and hence how many days are in the first week of the month.
To get the first Friday find the Saturday at the end of the week containing the second day of the month and subtract one to move back to Friday.
data want;
set example;
friday = intnx('week',date+1,0,'e')-1 ;
want = day(friday);
want_name=put(friday,downame.-l);
format friday date9.;
run;
Results:
Obs date dow downame friday want want_name
1 01OCT2000 1 Sunday 06OCT2000 6 Friday
2 01MAY2000 2 Monday 05MAY2000 5 Friday
3 01FEB2000 3 Tuesday 04FEB2000 4 Friday
4 01MAR2000 4 Wednesday 03MAR2000 3 Friday
5 01JUN2000 5 Thursday 02JUN2000 2 Friday
6 01SEP2000 6 Friday 01SEP2000 1 Friday
7 01JAN2000 7 Saturday 07JAN2000 7 Friday
To do it with any day in the month use the INTNX() function with MONTH interval to find the first day of the month (and add one to find the second day of the month).
length_week1=day(intnx('week',intnx('month',date,0,'b')+1,0,'e')-1);

Teradata SQL Week Number - Week 1 starting 1st Jan with weeks aligned to specific day of the week

my first post on here so please be gentle...
I'm trying to create a week number variable in Teradata (SQL) that does the following:
Week 1 always starts on 1st January of the given year
Week numbers increment on the specified day of the week
For example: If Saturday was the specified day of the week:
2019-01-01 would be the start of week 1, 2019, changing to week 2 on 2019-01-05
2020-01-01 would be the start of week 1, 2020, changing to week 2 on 2020-01-04
I have come up wit the following based on an Excel function however it doesn't quite work as expected:
ROUND(((DATE_SPECIFIED - CAST(EXTRACT(YEAR FROM DATE_SPECIFIED) || '-01-01' AS DATE) + 1) - ((DATE_SPECIFIED - DATE '0001-01-06') MOD 7 + 1) + 10) / 7) AS REQUIRED_WEEK
The last digit of the section - DATE '0001-01-06' deals with the specified day of the week, where '0001-01-01' would be Monday.
This works in some cases however for some years, the first week number is showing as 0 where it should be 1, e.g. 1st Jan 2018 / 2019 are fine whereas 1st Jan 2020 is not.
Any ideas to correct this would be gratefully received.
Many thanks,
Mike
You can apply NEXT_DAY for both the specified date and Jan 1st of that year, e.g. for Saturday as week start:
(Next_Day(DATE_SPECIFIED,'SAT') - Next_Day(Trunc(DATE_SPECIFIED,'yyyy'),'SAT')) / 7 +1
Hmmm . . . I'm a bit week on Teradata functions. But the idea is to get the start of the second week. This follows the rule:
Jan 1 weekday (TD) 2nd week
Sunday 1 01-02
Monday 2 01-08
Tuesday 3 01-07
Wednesday 4 01-06
Thursday 5 01-05
Friday 6 01-04
Saturday 7 01-03
I think the following logic calculates this:
select t.*,
(case when td_day_of_week(cast(extract(year from DATE_SPECIFIED) || '-01-01' as date) ) = 1
then cast(extract(year from DATE_SPECIFIED) + '-01-02' as date)
else extract(year from DATE_SPECIFIED) + 10 - cast(td_day_of_week(cast(extract(year from DATE_SPECIFIED) || '-01-01') as date)
from t;
Then do you your week calculate either from the second week or subtract one more week to get when the first week really starts.

date_format() unexpected results with <= or <= in where clause

We are using a built in calendar table dm_reference.dim_date with a sequence of dates:
select * from dm_reference.dim_date limit 10;
calendar_date date_name, day_of_week
1999-01-01 January 1, 1999 1 5 Friday
1999-01-02 January 2, 1999 2 6 Saturday
1999-01-03 January 3, 1999 3 7 Sunday
1999-01-04 January 4, 1999 4 1 Monday
1999-01-05 January 5, 1999 5 2 Tuesday
1999-01-06 January 6, 1999 6 3 Wednesday
1999-01-07 January 7, 1999 7 4 Thursday
1999-01-08 January 8, 1999 8 5 Friday
1999-01-09 January 9, 1999 9 6 Saturday
1999-01-10 January 10, 1999 10 7 Sunday
I wanted to filter this to only include dates between August 2014 and the current year month.
If I select min(date_format(calendar_date, "YYYYMM")) from dm_reference.dim_date I get returned 199901
So, I tried the following query to format my calendar_date field as year and month and then to filter to include dates between august 14 now:
select
distinct date_format(calendar_date, "YYYY-MMM") as year_month
, date_format(calendar_date, "YYYYMM") as year_month_num -- for ordering in asc
from dm_reference.dim_date
where date_format(calendar_date, "YYYYMM") <= 201408
and date_format(calendar_date, "YYYYMM") <= date_format(from_unixtime(unix_timestamp()), "YYYYMM")
order by year_month_num;
This returns dates going all the way back to 1999 whereas I expected the earliest date in this query result to be august 2014.
Any idea why this is happening? How can I query our calendar to only include a filtered date range?
I think you are complicating the query. You can simply filter for the required date range using
select *
from dm_reference.dim_date
where calendar_date >= '2014-08-01' and calendar_date < trunc(current_date,'MM')
This outputs all dates on or after August 2014 until the end of last month. If you need data until today, use the ending condition as calendar_date <= current_date.
The reason your query doesn't return expected results is because the condition is year month of calendar_date <= '201408' and year month of calendar_date <= '201808', which is everything before 201408.

Oracle query to count no of mondays......... sundays and total no of jobs on particular day in particular time?

I have a table
JobID Date_of_Completion Region day
1 23/05/2016 South monday
2 23/05/2016 north monday
3 23/05/2016 north monday
4 23/05/2016 east monday
5 22/05/2016 South sunday
6 22/05/2016 north sunday
7 22/05/2016 south sunday
8 22/05/2016 east sunday
.
.
.
..
23 2/05/2016 north monday
24 2/05/2016 east monday
25 2/05/2016 South monday
26 2/05/2016 north monday
27 2/05/2016 south monday
28 2/05/2016 east monday
desired output :
for last two months
Day Region countofjobsonparticularday no of days
sunday south 34 8 (no of sund forlast 2 months)
sunday north 24 8 (no of sund forlast 2 months)
monday south 74 9 (no of mon forlast 2 months)
tuesday east 64 8 (no of tue forlast 2 months)
how to write a query? plz help me
It seems that you need something like this:
select Day, Region, count(1), count(distinct date_of_completion)
from your_table
where date_of_completion between add_months(sysdate, -2) and sysdate
group by Day, Region
This will count the number of jobs and the number of DISTINCT days on which job completed.
You should refine this, based on your need ( for example how you want to consider hours, minutes, ...,)
If - as I suspect - you mean the last column, no of days, is supposed to show the total number of Mondays, Tuesdays, etc. over the last two months (regardless of whether there were any jobs on some of the days), first create a (sub)query as below and then join to Aleksej's result on the Day column. Speaking of Day, it is an Oracle keyword; it is always best to avoid using Oracle keywords as table or column names. I use day_name below.
Result of query (can be used as subquery):
DAY_NAME CT
--------------- ----------
monday 9
thursday 8
sunday 9
saturday 9
tuesday 8
friday 9
wednesday 8
I didn't order the results (not needed, if used for a join) and I used low-caps as the OP did. That is controlled by the format model (the middle argument to to_char in the query, below; if capitalized names, like Monday, are desired, change that from 'day' to 'Day').
Query:
with x (day_name) as (
select to_char(sysdate - level + 1, 'day', 'nls_date_language = American')
from dual
connect by level <= sysdate - add_months(sysdate, -2) - 1
)
select day_name, count(*) as ct
from x
group by day_name;
Note 'nls_date_language = American' - it is always best to make that explicit than to rely on default parameters. (Without this third argument, someone else running this with German or Chinese date language wouldn't get the expected result for joining with the other table.) Also, the definition of "last two months" is fuzzy; I used all days between today (included) and two months ago, that is between March 24 and May 23, 2016. These are controlled by the two expressions containing sysdate.
Thanks #mathguy and#Aleksej
I tried this query it worked
select to_char(dayofcompletion,'DY') as day_name, count(1),count(distinct(trunc(dayofcompletion))) as noofdays
from tablename
where trunc(dayofcompletion)>= trunc(sysdate-60)and trunc(dayofcompletion)<=trunc(sysdate-1)
group by to_char(dayofcompletion,'DY')