January 1st = Week 1 - sql

The below gives me week numbers where week 1 starts on 1/4/2021
date_trunc('week', transaction_date) as week_number
How can I create a week_number where the week starts on January 1st and counts up 7 days for every week thereafter (for every year)?
And round up/down to 52 weeks at the end of the year?
Code attempted:
This doesn't give me the answer, but I'm thinking something like this might work...
ceil(extract(day from transaction_date)/7) as week_number
Expected Output:
transaction_date
week_number
1/1/2020
1
1/8/2020
2
...
...
12/31/2020
52
1/1/2021
1
1/8/2021
2
...
...
12/27/2021
52
12/28/2021
52
12/29/2021
52
12/30/2021
52
12/31/2021
52
1/1/2022
1
Thanks in advance!

A simple way is to use date arithmetic:
select 1 + (transaction_date - date_trunc('year', transaction_date)) / 7 as year_week

The below gives me week numbers where week 1 starts on 1/4/2021
It is the default behaviour and it is defined that way in ISO.
WEEK_OF_YEAR_POLICY
Type Session — Can be set for Account » User » Session
Description
Specifies how the weeks in a given year are computed.
Values
0: The semantics used are equivalent to the ISO semantics, in which a week belongs to a given year if at least 4 days of that week are in that year.
1: January 1 is included in the first week of the year and December 31 is included in the last week of the year.
Default 0 (i.e. ISO-like behavior)
It could be overrriden on multiple levels. The most granular is on the session level:
ALTER SESSION SET WEEK_OF_YEAR_POLICY = 1;
Then you could use the standard code:
SELECT date_trunc('week', transaction_date) as week_number
FROM ...;

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.

Timeseries : date time averaging and abnormally detection

I"m dealing with a dataset with 4 week sales data (data will be refreshed every hour) and need to observer for abnormality
I think I'll go with a basic approach, to compare with average numbers and I'm trying to figure out how to best break this down so I can answer some questions below
On average, how many orders received at 9:00 , 15:00 or 16:00 past 30 days
On average, how many orders received at 9:00 every Wednesday (past 4 Wednesdays), at 15:00 every Thursday (past 4 Thursdays),
Not sure how do we go about this (after breaking date/time down to Hour and Weekday columns)
date
order ID
order hour
order weekday
10/07/2022 10:26:12 PM
1111
22
6
10/07/2022 10:27:12 PM
2222
22
6
....
....
....
....
19/07/2022 11:34:19 AM
9998
11
1
19/07/2022 11:34:35 AM
9999
11
1
I would love to get your advice please
Thanks
I've ended up going with a tedious approach.
#get current hour & weekday
now=datetime.datetime.now()
today=datetime.date.today()
current_hour=now.hour
current_weekday=today.weekday()
#create a DF with orders from the same hour & weekday window
same_hour_weekday_df=order_df[(order_df.order_hour==current_hour ) & (order_df.order_weekday==current_weekday) ]
#calculate avg orders generated from the past weeks within the same hour and weekyday timeframe
orders_same_hour_weekday=same_hour_weekday_df['order_created_at'].count()
same_hour_weekday_periods=same_hour_weekday_df['order_week'].nunique()
avg_orders_same_hour_weekday=orders_same_hour_weekday/same_hour_weekday_periods

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.

How can I calculate a fiscal week

I would like a column displaying the fiscal week. Our fiscal year begins in April.
So far I have the below, using datename(ww,DateAndTime) as Week
DateAndTime Week
2015-04-01 22:45 14
2015-06-14 13:22 25
2015-12-02 09:15 49
2016-01-01 07:35 1
I would like the output to show:
DateAndTime Week Fiscal Week
2015-04-01 22:45 14 1
2015-06-14 13:22 25 12
2015-12-02 09:15 49 36
2016-01-01 07:35 1 41
While I don't understand the logic behind the fiscal week (the difference between 1 and 41 is 40, but between 14 and 1 it's 39), maybe I'm missing something or you made a typo.
However, in general you'd do something like this (assuming the difference is 40 weeks):
SELECT week, (week+40)%52 AS fw FROM ...
If the fiscal year starts at a different week every each (say, 13th or 14th week depending on year), you can use the date and time functions, but they may vary between SQL versions. In MySQL you have YEAR(), MONTH(), WEEK(), etc.
For example:
SELECT week, (week+(52-WEEK(CONCAT_WS('-', YEAR(NOW()), '04-01'))))%52 FROM ...
But it might be overkill.
Note: It is possible to count the other way: if you subtract the diff from the week instead of adding, you will need to add 52 if the number is negative. You can do that by adding 52 and then doing modulo (%) 52.

Have someone a function in SQL that given a initial date, a day number and a final date calculate next matching day number and month?

I would like to know if someone have a function in SQL that given a initial date, a day number, a frecuency and a final date calculate next matching day number and month?
For example
#initialdate=20130101
#finaldate=20133112
#daynumber=14 --that means every 14
#frecuency=2
then the query generate the next dates like this:
20130114
20130314
20130514
20130714
20130914
20131114
Better if the solution is a CTE, better if validates 28-29 february and when day number is 31.
This is the query i'm working on, its about to generates date given a Type of Frecuency, a frecuency and a ocurrence that depends on the type of frecuency.
Type of Frec Frecuency Ocurrence
DI (Dairy) 1 (Every 1 day) na
DI (Dairy) 2 (Every 2 day) na
..
DI (Dairy) 6 (Every 6 day) na
SE (Weekly) 1 (Every 1 week) 1 (for Monday)
SE (Weekly) 2 (Every 2 weeks) 3 (for Wednesday)
SE (Weekly) 3 (Every 3 weeks) 5 (for Friday)
SE (Weekly) 4 (Every 4 weeks) 2 (for Tuesday)
MD (Monthly by day) 1 (Every 1 month) 1 (for first day of the month)
MD (Monthly by day) 1 (Every 1 month) 2 (for last day of the month)
...
MD (Monthly by day) 11 (Every 11 months) 2 (for last day of the month)
MF (Monthly by date) 1 (Every 1 month) 14 (for every 14 of the month)
...
MF (Monthly by date) 2 (Every 2 months) 30 (for every 30 of the month)
MF (Monthly by date) 3 (Every 3 months) 31 (for every 31 of the month)