Week number of 2021 starts with 53. I would want it to be 1. Every year week number has to reset and start with 1.
Example below query returns 1 in sql
select datepart(week,'2021-01-01')
But select week('2021-01-01'::date) return 53 in Snowflakes. I need the result to be 1 in snowflakes.
alter session set week_of_year_policy=1;
Added this before my query in snowflakes and now week number starts with 1 for year 2021.
Related
I have a Login Table like this:
Date,UserID
2020-08-01,1
2020-09-01,1
2020-09-07,2
2020-10-01,3
2020-10-12,4
2020-10-25,1
Basically, every time a user logins to my application, it register the date and the userID. I need to know the number of active users. To me an active user is one that has login in the previous thirty days of every day in the last week. For instance, let's say we are counting this week which goes from 2020-10-09 (October 9 2020) to 2020-10-15 (October 15 2020). Then I would go like this:
Check UserID = 1:
Has user login anytime between ('2020-10-09' - 30) and '2020-10-09'
Has user login anytime between ('2020-10-10' - 30) and '2020-10-10'
And so on until 2020-10-15
Then, it goes the same for each user ID.
In other words, I check the number of users that have login in a sliding Window of 30 days during a week. I hope this makes sense.
This is what I had in mind:
DROP TABLE IF EXISTS #ActiveUsers
CREATE TABLE #ActiveUsers (UserID bigint)
DECLARE #lowerDate Datetime='2020-10-09'
DECLARE #upperDate Datetime='2020-10-15'
DECLARE #activeSpan int=30
WHILE(#lowerDate <= #upperDate)
BEGIN
SELECT e.UserID INTO #ActiveUsers FROM
(SELECT DISTINCT(UserID) FROM logins WHERE Date >= (#lowerDate - #activeSpan)) AS e
WHERE e.UserID NOT IN (SELECT UserID FROM #ActiveUsers)
SET #lowerDate = #lowerDate + 1
END
PRINT SELECT COUNT(*) FROM #ActiveUsers
My reasoning was like this:
Check unique UserIDs in the timeframe.
Insert the unique ones in the temporary table as ling as they have not been previously inserted
Count the total after looping through the selected dates.
But besides being quiet inelegant I have not been able to make it work.
I would appraciate any advice.
Thank you!
I'm not sure if I understand the requirement - but let me confirm my understanding
Let's assume your 'upperDate' is 7 October. That means you would like to check that a user had done all of the following
Had logged in between 1 Sep and 1 October
Had logged in betweem 2 Sep and 2 October
...
Had logged in between 7 Sep and 7 October
Now, imagine three users, all who had logged in only once
The first logged in on 20 September
The second logged in on 3 September
The third logged in on 3 October
Their results would be as follows
The first would count as active as they were identified by all 7 tests.
The second would not count as active as they fail the tests from '4 Sep to 4 Oct' and later.
The third would not count as active as they fail the tests from '1 Sep to 1 Oct' and '2 Sep to 2 Oct'.
In other words - I think all you need to do is find the logins between your upperdate minus 30 days, to upperdate minus 7 days.
As such you wouldn't need a loop - the easiest check is
DECLARE #upperDate Datetime = '20201015';
DECLARE #activeSpan int = 30;
SELECT DISTINCT(UserID)
FROM logins
WHERE [Date] >= DATEADD(day, - #activeSpan, #upperDate)
AND [Date] <= DATEADD(day, -7, #upperDate);
Snowflake Database:
I have a day level table , i am trying use the day column to create a week column with the value of first Monday's of the week as a week value using following function. even though the table have a data for all seven days ( Monday through Sunday ) of the week. The following function will create a week column with five working days ( Monday through Friday) only rolled up to a week leaving Saturday and Sunday. is there any function which i can use to grab all seven days of data under one week in SNOWFLAKE DATABASE (first monday of the week).
CURRENT FUNCTION USED:
select dateadd('day', (extract('dayofweek_iso', current_date()) * -1) +1 , current_date() );
Snowflake provides DATE_TRUNC() to roll up date to corresponding year/month/week/day.
For the mentioned use case following query will roll up to Monday of the week.
select date_trunc('WEEK',current_date()) ;
Snowflake last_day() function can be used to achieve that. You can easily get the last day of week (Sunday) and subtract 6 days to get the first day of that week (Monday) like that:
select last_day(current_date(), 'week')-6 as first_day_of_week;
Business starts from Monday and ends on Sunday as a complete week. So I need to group by week in SSRS. How can I do this?
I am attaching the screenshot of my requirement.
Any help will be greatly appreciated.
User SET DATEFIRST 1;
DATEFIRST will set the first day of the week according to value given. 1 is for Monday, 2 TUESDAY and so on.
It will always have a fixed value for days. Like 1 will always be Monday and 7 will always be Sunday.
SELECT ##DATEFIRST will give the Week start day. By default it will be 7 i.e. Sunday. So if you run SET DATEFIRST 1 then SELECT ##DATEFIRST will return 1.
You may have to put SET DATEFIRST 1 inside Stored Procedure along with your query.
Why is this returning 4 instead of 6?
SET DATEFIRST 1
SELECT DATEDIFF(WEEK, CAST('2017-01-01' AS DATE), CAST('2017-01-31' AS DATE))
Is week as datepart calculating only weeks from monday - sunday (whole weeks)? How to get all weeks - including those which doesn't have seven days ? In the case above answer should be 6.
DATEDIFF counts transitions, not periods (e.g. look at DATEDIFF(year,'20161231','20170101')). It also treats Sunday as the first day of the week. So, how do we compensate for these features? First, we shift our dates so that Mondays are the new Sundays, and second we add 1 to compensate for the Fence-Post error:
declare #Samples table (
StartAt date not null,
EndAt date not null,
SampleName varchar(93) not null
)
insert into #Samples (StartAt,EndAt,SampleName) values
('20170101','20170131','Question - 6'),
('20170102','20170129','Exactly 4'),
('20170102','20170125','3 and a bit, round to 4'),
('20170101','20170129','4 and 1 day, round to 5')
--DATEDIFF counts *transitions*, and always considers Sunday the first day of the week
--We subtract a day from each date so that we're effectively treating Monday as the first day of the week
--We also add one because DATEDIFF counts transitions but we want periods (FencePost/FencePanel)
select *,
DATEDIFF(WEEK, DATEADD(day,-1,StartAt), DATEADD(day,-1,EndAt)) +1
as NumWeeks
from #Samples
Results:
StartAt EndAt SampleName NumWeeks
---------- ---------- -------------------------- -----------
2017-01-01 2017-01-31 Question - 6 6
2017-01-02 2017-01-29 Exactly 4 4
2017-01-02 2017-01-25 3 and a bit, round to 4 4
2017-01-01 2017-01-29 4 and 1 day, round to 5 5
If this doesn't match what you want, perhaps you can adopt and adapt my #Samples table to show the results you do expect.
What you ask though, is how many weeks are covered by a range, not how many weeks are between two dates.
DATEDIFF always uses Sunday when calculating week transitions.
This isn't a bug, it's done to ensure the function is deterministic and returns the same value, for every query, no matter the DATEFIRST setting. From the documentation
Specifying SET DATEFIRST has no effect on DATEDIFF. DATEDIFF always uses Sunday as the first day of the week to ensure the function is deterministic.
One solution would be to calculate the difference between the week numbers of the start and end dates, when the first day is Monday. 1 is added to the difference to take account of the first week as well:
SET DATEFIRST 1;
select 1 +datepart(WEEK,'20170131') - datepart(WEEK,'20170101')
That's a fragile calculation though that breaks if DATEFIRST changes or if one of the dates is on a different year.
You could use ISO Weeks to get rid of SET DATEFIRST:
select 1 +datepart(ISO_WEEK,'20170131') - datepart(ISO_WEEK,'20170101')
but that would fail for 2017-01-01 because Sunday is counted as Week 52 of the previous year.
A far better solution though would be to count the distinct week numbers using a Calendar table that contains dates and different week numbers to cover multiple business requirements, eg both normal and ISO Week numbers, or business calendars based on a 4-4-5 calendar.
In this case, you could just count distinct week numbers:
SELECT COUNT(DISTINCT Calendar.IsoWeek )
from Calendar
where date between '20170101' and '20170131'
If the table doesn't have an ISO Week column, you can use DATEPART:
select count (distinct datepart(ISO_WEEK,date) )
from Calendar
where date between '20170101' and '20170131'
My requirement is that I want to find business-week-ending (not the calender week) given a DATE column from the sales table in MSSQL.
Using different techniques I was able to find the [Calender] week-endings (and week-starting) dates corresponding to DATE in the table.
Since our business week ends on Wednesday [DOW 3 or 4 depending when the week started], I tried to deduct number of days from the week ending dates to pull it back to Wednesday. The idea did work pretty good with a flaw. Works fine as long as the Date in the table is greater than DOW 3 or 4. Any suggestion?
SELECT DateAdd(wk, DateDiff(wk, 0, Recons_Sales_Details.Recons_Date), 0) + 2
You need to look into SET DATEFIRST to do this:
SET DATEFIRST 4 --4 is Thursday week start
SQL Fiddle Demo