Current week in current month showing wrong in SQL Server - sql-server

This is how the July month looks like.
I am trying to pick the current week in current month with getdate() parameter using the below code.
declare #date datetime = getdate()
select datepart(day, datediff(day, 0, #date) / 7 * 7) / 7 + 1
Expecting the result as
Date -> week Number
2015-07-01 -> 1
2015-07-06 -> 2
2015-07-13 -> 3
But, instead, the result is:
Date -> week Number
2015-07-01 -> 5
2015-07-06 -> 1
2015-07-13 -> 2
How do I get the first format in SQL Server?
Thanks in advance

This seems to get the right answer
select datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, #date), 0)), 0), #date)+1

Related

SQL Server: Calculate Four Weeks From a Month

I need a simple solution to get 4 weeks for a month based on current date (each week starting from Monday - Friday).
For each week I need to update a table that already has current date and place a counter from Week 1 - 4 and continue to the following month starting from Week 6 - 8. and start from the beginning after week 8.
The query below is returning week number but for 7 days:
can I use something similar just for 5 days?
DECLARE #MyDate DATETIME = '2020-08-03'
--This assumes the weeks starts from Monday - Sunday
DECLARE #WeekNumber INTEGER = (DATEPART(DAY, DATEDIFF(DAY, 0, #MyDate)/7 * 7)/7 +1)
SELECT #WeekNumber
The previous answer was not useful so I got rid of it. This should do what you're looking for
declare #date datetime= '2020-08-03';
select dateadd(d, -4, dt.dt) start_dt,
dt.dt end_dt,
row_number() over (order by v.n) n
from
(select datefromparts(year(#date),month(#date),1) first_dt) fd
cross apply
(select datediff(week, 0, fd.first_dt) wk_diff) wd
cross apply
(values (1),(2),(3),(4),(5),(6)) v(n)
cross apply
(select dateadd(d, -((datepart(weekday, fd.first_dt) + 1 + ##datefirst) % 7), fd.first_dt) calc_dt) calc_dt
cross apply
(select dateadd(d, (v.n-1)*7, calc_dt) dt) dt
where
dt.dt>=fd.first_dt;
Results
start_dt end_dt n
2020-08-03 2020-08-07 1
2020-08-10 2020-08-14 2
2020-08-17 2020-08-21 3
2020-08-24 2020-08-28 4
2020-08-31 2020-09-04 5

SQL: produce aggregate results table for the last 12 months, excluding the current month

Using SQL Server 2008 R2, I've written some code to produce an aggregate results table that calculates the average wait time (from referral to appointment date) for all appointments within the month.
Based on whatever day the query is run, I want it to produce me a table of results for the previous 12 full months, excluding the current month. So for example, if I run the query today (6th Sept 2017), I want the table of results to give me 12 rows for the months August 2017 back to Sept 2016, like this:
YEAR | MONTH | MONTHNAME | AVG DAYS WAIT
-----+-------+-----------+---------------
2017 | 8 | August | 42
2017 | 7 | July | 43
2017 | 6 | June | 47
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2016 | 9 | September | 42
I'm using the following code which does indeed return me a 12 month list and excludes the current month:
SELECT
year (OP.Appointment_Date) [Year]
,month (OP.Appointment_Date) [Month]
,DATENAME (month,OP.Appointment_Date) [MonthName]
,AVG(DATEDIFF (dd,OP.Received_Date,Appointment_Date)) [Avg Days Wait]
FROM
[HDM_Local].[Outpatients].[vw_OP_Appointments] OP WITH (NOLOCK)
WHERE
OP.Appointment_Date >= DATEADD(month, -12, GETDATE())
AND OP.Appointment_Date < DATEADD(month, -1, GETDATE())
GROUP BY
year(OP.Appointment_Date)
,month(OP.Appointment_Date)
,DATENAME(month,OP.Appointment_Date)
ORDER BY
year(OP.Appointment_Date)desc
,month(OP.Appointment_Date)desc
However, the problem I've found is that the result for the most recent month (August) is incorrect.
I know from validating my data that the average wait time in August was 42 days. The query above is actually giving me a figure of 50.
I'm presuming that what's happening is the AND OP.Appointment_Date < DATEADD(month, -1, GETDATE()) statement is taking today's date, subtracting a full month's worth of days from it, and then calculating the average wait time for appointments in August based only on those appointments dated between 1st-6th August (or something along these lines).
The same issue also appears to be influencing the result for the oldest month in the list, I presume again because it's ignoring the first 5/6 days during Sept 2016 when performing the calculation.
Please can anyone explain how to code the statement to effectively "ignore the current month and return the previous 12 months, based on the full range of dates within each month"?
Your where clause is subtracting months, but is not truncating to the start of each month.
This will give you the range that starts from the first day of the month 12 months ago through the end of last month:
where op.Appointment_Date >= dateadd(month, datediff(month, 0, getdate() )-12, 0)
and op.Appointment_Date < dateadd(month, datediff(month, 0, getdate() ), 0)
Here is a comparison of your date range, vs a truncated to month date range:
select
TruncatedToMonth = 'N'
, fromdate = dateadd(month, -12, getdate())
, thrudate = dateadd(month, -1, getdate())
union all
select
TruncatedToMonth = 'Y'
, fromdate = dateadd(month, datediff(month, 0, getdate() )-12, 0)
, thrudate = dateadd(month, datediff(month, 0, getdate() ), 0)
rextester demo: http://rextester.com/RGJ79943
returns:
+------------------+---------------------+---------------------+
| TruncatedToMonth | fromdate | thrudate |
+------------------+---------------------+---------------------+
| N | 2016-09-06 14:38:07 | 2017-08-06 14:38:07 |
| Y | 2016-09-01 00:00:00 | 2017-09-01 00:00:00 |
+------------------+---------------------+---------------------+
WHERE
OP.Appointment_Date >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-12, 0)
AND OP.Appointment_Date < DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1)
--or --
WHERE
OP.Appointment_Date between DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-12, 0)
AND DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1)
Basically:
select DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) --First day of previous month
select DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1) --Last Day of previous month
I would personally remove your logic from the where clause and place them into a variable since they do not rely on columns (will reduce your overhead either a negligible amount or substantial, depending on your database).
Try these variables in your where clause, should return beginning of September 2016 to end of August 2017
DECLARE #MinDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-12, 0) -- Get start of month 13 months before current
DECLARE #MaxDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), -1) -- Get end of latest month before current
SELECT #MinDate, #MaxDate
EDIT: Just re-reading your post. The way that DATEADD MONTH works, is to literally add or subtract that number of months from the date i.e. if it is the 6th September 2017, take 12 months from that which returns the 6th September 2016. You can always take clauses like that out of your WHERE clause and place them into a select to see the effect they're having i.e.:
SELECT DATEADD(month, -12, GETDATE()), DATEADD(month, -1, GETDATE())
Returning
(No column name) (No column name)
2016-09-06 18:45:07.857 2017-08-06 18:45:07.857

Add a number (13) to the month and change the day to the 1st of that month

I am sure this one is simple but I am having a difficult time figuring it out. I am trying to add 13 months to a date and that resulting month needs to default to the 1st day of the month.
Example:
Date: 1/25/2016
Query results: 2/1/2017
Here is the query I am using:
SELECT Dateadd(month,13,getdate())
This should work for you. Just replace GETDATE() with your date.
select dateadd(month, datediff(month, 0, dateadd(month, 13, GETDATE())), 0)
SQL 2012+
SELECT DATEADD(DAY, 1, EOMONTH(GETDATE(), 12))
You can just construct the date from the constituent parts, by adding 1 year + 1 month and forcing the day part to 1 (and taking care of the special case of month = 12), like this:
select DATEFROMPARTS (
year(getdate()) + case when month(getdate()) = 12 then 2 else 1 end,
case when month(getdate()) = 12 then 1 else month(getdate()) + 1 end,
1
)

Date Range of the x-th week in SQL Server?

I know the year and the index of the week, i.e. 2014, the 5th week. how can I find out the starting and ending date of this week in SQL Server? I do not really care whether the week starting with Monday or Sunday.
In mySQL, it has a MakeDate which may be able to do this. Is there an existing way to do this in SQL Server?
Thanks
Try this.
DECLARE #date DATE='2014-01-01'
SELECT Dateadd(dd, -( Datepart(dw, Dateadd(wk, 5, #date) - 1) ), Dateadd(wk, 5, #date)) [WeekStart],
Dateadd(dd, 7 - ( Datepart(dw, Dateadd(wk, 5, #date)) ), Dateadd(wk, 5, #date)) [WeekEnd]
SELECT
dateadd(wk,5,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)) as firstdayof5thweek2014,
dateadd(dd,6,dateadd(wk,5,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))) as lastdayof5thweek2014
SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0) ==>gives you start day of the current year
SELECT dateadd(wk,5,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)) ==> On top add 5 weeks to get the start date of 5th week in 2014
SELECT dateadd(dd,6,dateadd(wk,5,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))) ==> On top add 6 days to get the last date of 5th week in 2014

Microsoft SQL Calculating Backlog

I would like to calculate the backlog for every week in the past month. Date format is in (MM/DD/YY)
| mutation | issued_date | queryno_i | status |
-----------------------------------------------
01/05/14 12/31/13 321 OPEN
01/02/14 08/01/13 323 CLOSED
01/01/14 06/06/13 123 OPEN
01/01/14 01/01/14 1240 CLOSED
01/02/14 01/01/14 1233 OPEN
01/03/14 01/03/14 200 CLOSED
01/05/14 01/04/14 300 OPEN
01/06/14 01/05/14 231 OPEN
01/07/14 01/06/14 232 CLOSED
01/09/14 01/10/14 332 OPEN
01/11/14 01/11/14 224 CLOSED
01/15/14 01/14/14 225 CLOSED
01/16/14 01/15/14 223 OPEN
I want my result set to look like this:
WeekNum | Opened | Closed | Total Open
--------------------------------------
1 4 3 4 <= (2-4)+ data in week 2 so (2-4)+(1-2)+7
2 4 2 6 <= (1-2)+7
3 2 1 7 <= total count
My Code is below however I am not sure how to query the last part. I am not even sure if this is possible or not.
WITH
issued_queries AS
(
SELECT DATEPART(wk, issued_date) AS 'week_number'
,COUNT(queryno_i) AS 'opened'
FROM t.tech_query
WHERE DATEADD(D,-12,issued_date) > GETDATE()-40
GROUP BY DATEPART(wk, issued_date)
),
closed_queries AS
(
SELECT DATEPART(wk, mutation) AS 'week_number'
,COUNT(queryno_i) AS 'closed'
FROM t.tech_query
WHERE status=3 AND DATEADD(D,-12,issued_date) > GETDATE()-40
GROUP BY DATEPART(wk, mutation)
),
total as
(
SELECT COUNT(*) AS 'total'
FROM t.tech_query
WHERE status!='3'
)
SELECT issued_queries.week_number
, issued_queries.opened
, closed_queries.closed
FROM issued_queries JOIN closed_queries
ON (issued_queries.week_number = closed_queries.week_number)
ORDER BY week_number
Backlog for every week in the past month.
I've taken this to mean last 4 weeks, as that appears to be what you are doing.
Assuming "mutation" represents the date a record was updated (maybe set to closed).
So first, I generate a list of dates, so that way there will be an answer for week number X even if there are no new/closed records.
declare #SundayJustGone datetime
-- We need to get rid of the time component, done through convert.
set #SundayJustGone = convert(date, dateadd(d, 1-DATEPART(dw, getdate()), getdate()))
-- If earlier than sql 2008, can get rid of time component through: set #SundayJustGone = SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, #SundayJustGone))
;with
Last4Weeks as
(
-- Get the sunday of the week just gone.
select #SundayJustGone as SundayDate -- Sunday just gone
union all
select dateadd(d, -7, SundayDate) -- Get the previous Sunday
from Last4Weeks
where dateadd(d, -7, SundayDate) > dateadd(Wk, -4, #SundayJustGone) -- where the new date is not more than 4 weeks old
)
select A.SundayDate,
DATEPART(wk, DateAdd(d, -1, A.SundayDate)) as Week_Number, -- SQL considers Sunday the first day of the week, so we need to move it back 1 day to get the right week
(select count(*)
from t.tech_query
where issued_date between DateAdd(d, -6, A.SundayDate) and A.SundayDate -- Was issued this week. (between monday - sunday)
) as Opened,
(select count(*)
from t.tech_query
where status = 3 -- where it is closed
and mutation between DateAdd(d, -6, A.SundayDate) and A.SundayDate -- and the mutation was this week. (between monday - sunday)
) as Closed,
(select count(*)
from t.tech_query
where (status != 3 or datediff(d, mutation, A.SundayDate) < 0 ) -- Is still open, or was closed after this week.
and datediff(d, issued_date, A.SundayDate) >= 0 -- and it was issued on or before the sunday.
) as TotalOpen
from Last4Weeks as A
hopefully this helps.
the results are different to yours, as I assume Monday is the first day of the week. To change start of week back to sunday, saturday needs to be considered end of week, so, change the set #SundayJustGone = convert(date, dateadd(d, 1-DATEPART(dw, getdate()), getdate())) to set #SundayJustGone = convert(date, dateadd(d, -DATEPART(dw, getdate()), getdate())) (1 removed)

Resources