SELECT
DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 6 - DATEPART(DAY, GETDATE()),
GETDATE())), 0),'First Monday of Current Month'
This query returns the first Monday of the current month. I just want to know how this query is working and how do I get the first Wednesday of the current month instead.
Let's simplify the whole:
SELECT DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, GETDATE()), GETDATE())), 0)
you can think at it in this way:
-- number of day to go back to reach 1st week of month
z = 6 - DATEPART(DAY, GETDATE())
-- a day in 1st week of the month
y = DATEADD(DAY, z, GETDATE())
-- number of weeks between 0 (1900-01-01) and 1st week of month
x = DATEDIFF(WEEK, 0, y)
-- add the number of weeks elapsed to 1900-01-01 to get the datetime of 1st day of 1st week of month
SELECT DATEADD(WEEK, x, 0)
I just want to know how this query is working
SELECT DATENAME(WEEKDAY, '1900-01-01') --'Monday'
SELECT DATENAME(WEEKDAY, 0) --also 'Monday'
January 1, 1900 was a Monday. When you add a week to a Monday you get another Monday. If you add 6,170 weeks to a Monday- you still get a Monday. As of 04/10/2018 there have been 6,170 weeks since Jan 1, 1900.
Simply, the query calculates these weeks, adding 6,170 weeks since Monday, Jan 1 1900.
how do I get the first Wednesday of the current month instead?
SELECT DATENAME(WEEKDAY, '1900-01-03') --Wednesday
SELECT DATENAME(WEEKDAY, 2) --also Wednesday
January 3, 1900 is represented by integer 2. We changed a 0 (which was monday) to a 2 (wednesday). If you add 6,170 weeks to a Wednesday you still get a Wednesday.
In the query there is a 0. We can change this to a 2:
SELECT
DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 6 - DATEPART(DAY, GETDATE()),
GETDATE())), 2),'First Wednesday of Current Month'
Edit: I can make this perhaps a little clearer by getting rid of the integer and putting in the actual date:
SELECT
DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 6 - DATEPART(DAY, GETDATE()),
GETDATE())), '1900-01-03'),'First Wednesday of Current Month'
This will give you the first Wednesday of the month, as requested in your comment:
SELECT
DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 6 - DATEPART(DAY, GETDATE()), GETDATE())), 2)
AS 'First Wednesday of Current Month'
I changed your last 0 in the DATEADD function to a 2, as this is a zero based representation of the days of the week, 0 being Monday.
You can use the "Try it yourself" functionality on W3schools to play around with queries and figure them out: W3schools. Just paste your query in the console.
I tried many formula to get first Wednesday of the current month including above scripts but they were not working right if the month starts with Wednesday. (2022-06-01 can be tried). So I succeed it with my own way, you can see the sql below.
select
FirstWednesdayofCurrentMonth =
case when datepart(dw,EOMONTH(dateadd(month,-1,getdate()))) = 3
then dateadd(dd,1,EOMONTH(dateadd(month,-1,getdate()))) -- if month start with wednesday
else convert(date, DATEADD(DAY,(DATEDIFF(DAY,2,DATEADD(d,1,EOMONTH(dateadd(month,-1,getdate())))) / 7) * 7 + 7, 2)) -- if not
end
Related
The ultimate goal is to retrieve data (scheduling data) for the 3 weeks in the future, to be accurate next Monday (if today is Monday, this week should be skipped) and 3 weeks after next Monday (should be Sunday).
I ran my code yesterday (on Sunday) and it worked as expected, but when I ran it today (on Monday), dates didn't shift to the next week, they still showing same dates as yesterday.
SELECT CONVERT(CHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0), 120) AS [Next Monday]
SELECT CONVERT(CHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0) + 20, 120) AS [3 Weeks After Next Monday (Sunday)]
Today is 2022-02-21, therefore Next Monday date should be 2022-02-28 and 3 Weeks After Next Monday (Sunday) should be 2022-03-20
I believe the best way would be to use a resolution of days and divide and multiply out by 7, does the following work for you?
select DateAdd(day, (DateDiff(day, 0, GetDate()) / 7) * 7 + 7, 0) as NextMonday
I want to know the SQL Server query in which I can get record from the table against the specific day (like Monday OR Tuesday) of current week, OR against the specific day from the last 7 days.
Like I want to get record for 1st day of last 7 days OR Like I want to get record for the Monday OR Tuesday from current week.
By the way I can get specific day of current week through this SQL Server query
//Query
SELECT DATEADD(DD, 0 - DATEPART(DW, GETDATE()), GETDATE()) //Get Sunday
SELECT DATEADD(DD, 1 - DATEPART(DW, GETDATE()), GETDATE()) //Get Monday
SELECT DATEADD(DD, 2 - DATEPART(DW, GETDATE()), GETDATE()) //Get Tuesday
But I want to get record from the table against these days, like so:
Select * from tbl_Sale where date = "Here the specific day's date should be called"
Sorry for the long text but I really need to explain that what I need to do, so please if anyone can do this?
Return only those records where date is in the last 7 days and then further restrict your criteria to just Mondays.
SELECT *
FROM tbl_Sale
WHERE DATEDIFF(DAY, GETDATE(), date) BETWEEN -7 AND 0
AND DATENAME(WEEKDAY, date) = 'Monday'
This would also work.
SELECT *
FROM tbl_Sale
WHERE DATEDIFF(DAY, GETDATE(), date) BETWEEN -7 AND 0
AND DATEPART(WEEKDAY, date) = 2 -- by default 2 is equivalent to Monday
You will find a lot of valuable information reading up on Date and Time Data Types and Functions (Transact-SQL). So by default, DATEPART(WEEKDAY, date) will return 1 for any Sunday, 2 for any Monday, etc. However, you can set the first of the week to be whatever day you want by setting DATEFIRST.
Here is some sample code to show the Weekday Names and Weekday Numbers for a range of dates.
For the below query
Sum(CASE WHEN dbo.sales.date BETWEEN '2016-07-17' AND '2016-07-23' THEN dbo.sales.sellinc END) AS ActualSales
Instead of hard coding the date. I would like to pick current date from machine and compare
Sum(CASE WHEN dbo.sales.date BETWEEN '**previous week (31 week 2016)**' AND '**Last year same week (31 week 2015)**' THEN dbo.sales.sellinc END) AS ActualSales
Week start from Sunday and ends Saturday. Any help please?
I think this snippet might help you to get a range of one year from the previous week to last year.
Sum(CASE
WHEN dbo.sales.date
BETWEEN DATEADD(YEAR, -1, DATEADD(WEEK, -1, GETDATE())) AND
DATEADD(WEEK, -1, GETDATE()) THEN dbo.sales.sellinc END) AS ActualSales
You can also modify the logic if you want to consider Friday as an exception.
In that case, you have to use DATEPART(WEEKDAY, GETDATE()) function to get the week day which returns 1 for Sunday and 7 for Saturday. It would be prettier if you move the date generation logic to a variable and then use it to select your data.
Others have already noted that your method of week numbering is going to impact your solution. Here's one that just looks for the Sunday of the current week and then subtracts 52 weeks. (You could also just deduct 364 days in the previous step and use dateadd only once.) So the correspondence with the previous year's week is essentially the nearest calendar date falling on Sunday that year.
with dates as (
select
dateadd(week, -52,
dateadd(day,
1 - datepart(weekday, getdate()), /* Sunday of current week */
cast(getdate() as date)
)
) as WeekStartY-1,
dateadd(day, 1 - datepart(weekday, cast(getdate() as date)) as WeekStartY-0
)
select
sum(case when cast(s."date" as date)
between d.WeekStartY-0 and dateadd(day, 6, WeekStartY-0) then s.sellinc end
) as ActualSalesY-0,
sum(case when cast(s."date" as date)
between d.WeekStartY-1 and dateadd(day, 6, WeekStartY-1) then s.sellinc end
) as ActualSalesY-1,
from dbo.Sales s cross apply dates d;
This can occasionally produce an oddity where the weeks both start in the same year. It happens when the year ends on Sunday, or Monday in leap years, as with 2012. So Y-1 for December 30, 2012 was January 1, 2012. But consider that most of the days for that week actually fall in 2013 and the correspondence makes sense from that perspective.
You can try using DATEADD:
SUM(CASE WHEN dbo.sales.date BETWEEN DATEADD(week, 30, '2016/01/01') AND
DATEADD(week, 30, '2015/01/01')
THEN dbo.sales.sellinc END) AS ActualSales
This will give you the one year range between the 30th week of 2015 and 2016, using the SQL Server week, whose first week begins on January 1st, regardless of the day. If you really want to use the ISO week, then it will be a lot more work.
ApptStart
2005-02-18 10:00:00.000
2005-02-18 13:00:00.000
2005-02-18 11:00:00.000
2005-02-21 09:00:00.000
2005-02-18 15:30:00.000
2005-02-18 14:30:00.000
.
.
.
I have a column in our database that looks like the above. I want to count appointments for the month for a given doc. On Fridays most of them do a half day. So I do not want to count Fridays with appointments only in the morning. If the appointment is in the afternoon, after 12:00:00.000 I want to include that day in the distinct count.
So far I have:
SELECT
ScheduleDays = count(distinct CONVERT(datetime, convert(char(12), a.ApptStart, 1)))
FROM Appointments a
WHERE
ApptKind = 1 AND
--filter on current month
a.ApptStart >= ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0),'1/1/1900') AND
a.ApptStart < ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE())+1, 0),'1/1/3000') AND
--Filter on doctor
a.ResourceID in (201)
This worked when I counted every day with appointments on it, but like I said I need to exclude those half days.So I was thinking about only looking at the last right chars of the ApptStart and comparing it x > noon in a case inside the distinct count...
I tried the following, but it did not work:
ScheduleDays = count(distinct case when (Right(a.ApptStart, 12)) > '12:00:00:000' then 1 else 0 END)
Thanks in advance!
EDIT
I tried:
SELECT
ScheduleDays=COUNT(DISTINCT(CAST(datediff(d,0,a.ApptStart) as datetime)))
FROM Appointments a
WHERE
ApptKind = 1 AND
--filter on current month
a.ApptStart >= ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0),'1/1/1900') AND
a.ApptStart < ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE())+1, 0),'1/1/3000')AND
--filter all days that aren't Friday, and then give you all Fridays with an hour > 12.
DATENAME(weekday, a.ApptStart) <> 'Friday' OR DATEPART(hour, a.ApptStart) > 12 AND
--Filter on doctor
a.ResourceID in (201)
for 1808 as the count
You probably want to treat dates as dates, rather than strings. You can determine whether a particular timestamp is on a Friday -- or the hour of a timestamp -- using DATEPART, without having to CONVERT it into a CHAR:
datename(weekday, timestamp_value) -- returns Friday
datepart(weekday, timestamp_value) -- returns either 5 or 6, depending on the value of SET DATEFIRST. (Get day of week in SQL 2005/2008)
datepart(hour, timestamp_value) -- returns hour part
Using these, you can test whether a timestamp is on Friday at or after noon by checking if datepart(weekday, timestamp_value) = 6 and datepart(hour, timestamp_value) >= 12.
bendataclear pointed out that you're using distinct on a case statement which can only ever return 0 or 1, so your total will only ever be 0, 1, or 2. If you're trying to determine which days the doctors worked more than half a day, you'll need to select distinct dates --
SELECT COUNT(DISTINCT(CAST(datediff(d,0,timestamp_value) as datetime)))
FROM table_name
WHERE DATENAME(weekday, timestamp_value) <> 'Friday' OR DATEPART(hour, timestamp_value) > 12
AND the rest of your filters here
The WHERE clause there will give you all days that aren't Friday, and then give you all Fridays that have an hour > 12.
I have to collect all the rows in a table where they were inserted on a Monday for the last 3 three months. How would I write the WHERE clause date to get those results?
WHERE Date = (wk, DATEDIFF(wk,0,GETDATE()), 0)
That will select everything from Monday of the current week, but what I am having a problem with is selecting a range of Mondays going back three months.
thanks!
So this is the WHERE clause I ended up with that works well for me....
where Datestamp > dateadd(month, -3, getdate())
AND datepart(weekday, Datestamp) = datepart(weekday, DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
I changed only the part where we enter the day of the week that starts on Monday I added this...
DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
WHERE Date > dateadd(month, -3, getdate())
AND datepart(weekday, Date) = 1
These are two separate conditions; no need to compress them into one.
Note: run a test on your machine to see which value you get for datepart(weekday, #AMondayDate). On some systems Monday is 1, on others is 2; it depends on the DATEFIRST configuration.
Update:
Thanks to ErikE for the clever trick that overcomes the weekday numbers issue:
WHERE Date > dateadd(month, -3, getdate())
AND datepart(weekday, Date) = datepart(weekday, '2012-11-25')