SQL Query errors doesn't return values for Fridays - sql

I have this sql stored procedure which is supposed to look at a particular table and return job numbers based on a date column. This works great except for when its run Saturday morning (and should return all job numbers with a date of Friday, but returns no rows). Any suggestions? Is there some logic problem here I'm not seeing? How might I track this down?
Stored Procedure
ALTER Procedure [dbo].[JC_GetJobsClosedYesterday]
As
SELECT [JobNumber]
FROM [NCLGS].[dbo].[JobClosedDate]
Where LastInvoiceDate between dbo.ufn_StartOfDay (DATEADD(d, -1, GETDATE())) AND dbo.ufn_StartOfDay (GETDATE())
order by JobNumber desc
And the start of day function.
ALTER function [dbo].[ufn_StartOfDay] ( #inDate datetime )
RETURNS DateTime AS
BEGIN
DECLARE #Now datetime
set #Now = #inDate
DECLARE #DayStart datetime
set #DayStart = #Now
set #DayStart = DATEADD (ms, -DATEPART(ms,#Now),#DayStart)
set #DayStart = DATEADD (s, -DATEPART(s,#Now),#DayStart)
set #DayStart = DATEADD (mi, -DATEPART(mi,#Now),#DayStart)
set #DayStart = DATEADD (hh, -DATEPART(hh,#Now),#DayStart)
return #DayStart
END
EDIT: I'm not having trouble with my date conversion (unless it doesn't know how to handle Fridays). I need help with the returning no rows part.
SAMPLE DATA:
JobNumber LastInvoiceDate DayOfWeek
112117 2011-06-13 00:00:00.000 Monday
112089 2011-06-10 00:00:00.000 Friday
112090 2011-06-10 00:00:00.000 Friday
112068 2011-06-10 00:00:00.000 Friday
112082 2011-06-10 00:00:00.000 Friday
UPDATE: Now I'm really confused. This "no data on fridays" thing has been happening (happened again last friday), but I still can't figure it out. Is it possible that GETDATE() isn't returning what I think its returning? Because when I try the following modifications based on #Thomas's suggestion, both methods get data, but the report that generated based on this code last sat has no data.
DECLARE #date datetime
--SET #date = '2011-06-21 13:42:27.257'
SET #date = '2011-06-11 03:42:27.257'
--Original Code
SELECT [JobNumber]
FROM [NCLGS].[dbo].[JobClosedDate]
Where LastInvoiceDate between dbo.ufn_StartOfDay (DATEADD(d, -1, #date)) AND dbo.ufn_StartOfDay (#date)
order by JobNumber desc
--Returns 21 records
--Modified based on #Thomas suggestion
Select [JobNumber]
From [NCLGS].[dbo].[JobClosedDate]
Where LastInvoiceDate >= DateAdd( d, DateDiff( d, 0, #date ) - 1, 0 )
And LastInvoiceDate < DateAdd( d, DateDiff( d, 0, #date ), 0 )
Order By JobNumber Desc
--Returns 21 records

Instead of DATEADD(d, -1, GETDATE()) you should use an expression that returns the beginning of the previous day. You could use your dbo.ufn_StartOfDay() function for that, but there's simpler way to do the same:
Select #DayStart = DateAdd( d, DateDiff( d, 0, #inDate ), 0 )
which means: increase the nil timestamp by the whole number of days between the nil timestamp and the given one.
I would also suggest using that expression instead of the already present call to the function as well, so your query would be:
Select [JobNumber]
From [NCLGS].[dbo].[JobClosedDate]
Where LastInvoiceDate Between DateAdd( d, DateDiff( d, 0, GetDate() ) - 1, 0 )
And DateAdd( d, DateDiff( d, 0, GetDate() ), 0 )
Order By JobNumber Desc
Addition
You need to be clearer about where exactly the problem is. Here is a sample query I created which tests every date from Thursday, June 9 through Saturday June 18. On which date did you expect to get values but did not or visa versa:
With SampleData As
(
Select 112117 As JobNumber, '2011-06-13 00:00:00.000' As LastInvoiceDate, 'Monday' As DayOfWeek
Union All Select 112089, '2011-06-10 00:00:00.000', 'Friday'
Union All Select 112090, '2011-06-10 00:00:00.000', 'Friday'
Union All Select 112068, '2011-06-10 00:00:00.000', 'Friday'
Union All Select 112082, '2011-06-10 00:00:00.000', 'Friday'
)
, TestDates As
(
Select Cast('20110609' As datetime) As Date
Union All
Select DateAdd(d,1,Date)
From TestDates
Where Date <= '20110617'
)
Select TD.Date, DateName(dw,TD.Date), Count(SD.JobNumber)
From TestDates As TD
Left Join SampleData As SD
On SD.LastInvoiceDate Between DateAdd( d, DateDiff( d, 0, TD.Date ) - 1, 0 )
And DateAdd( d, DateDiff( d, 0, TD.Date ), 0 )
Group By TD.Date
Update
In looking at your comments and the code, I think the problem is in your use of Between. Col Between DateA And DateB translates to Col >= DateA And Col <= DateB. I.e., it is inclusive of both end points. Instead, you need to exclude the final end point:
Select [JobNumber]
From [NCLGS].[dbo].[JobClosedDate]
Where LastInvoiceDate >= DateAdd( d, DateDiff( d, 0, GetDate() ) - 1, 0 )
And LastInvoiceDate < DateAdd( d, DateDiff( d, 0, GetDate() ), 0 )
Order By JobNumber Desc
This will give you all job numbers that on the previous date. I.e, if today is Friday, June 10, 2011, it will give you all LastInvoiceDate values from 2011-06-09 midnight through 2011-06-09 23:59:59.

See Floor a date in SQL server
To strip the time portion use:
SELECT CAST(FLOOR(CAST(CURRENT_TIMESTAMP AS float)) AS DATETIME)
This should be the fastest way. Thus
SELECT [JobNumber]
FROM [NCLGS].[dbo].[JobClosedDate]
WHERE LastInvoiceDate between
CAST((FLOOR(CAST(GETDATE() float))-1.0) AS DATETIME) AND
CAST(FLOOR(CAST(GETDATE() AS float)) AS DATETIME)
ORDER BY JobNumber DESC

The procedure which updates the jobclosed table runs Monday, Tuesday, Wednesday, Thursday, & Friday mornings. It doesn't run on Saturdays, so the records aren't inserted until monday, at which time they won't be retrieved by my stored procedure. I will schedule the update job to run on Saturday's also.
I added the following before the select statement:
if datepart(dw, GETDATE()) = 7 OR datepart(dw, GETDATE()) = 1
BEGIN
Exec dbo.NCL_MaintainJobClosedDateTable
--Select 'True'
END
Which will force an update on Saturday and Sunday mornings.

Related

Today Production - SQL Date Calculation case when

I have an issue regarding date calculations.
I have a datetime column called CreatedLocalTime date with this format: 2015-11-15 19:48:50.000
I need to retrieve a new column called Prod_Date with:
if “CreatedLocalTime” between
(CreatedLocalTime 7 AM)
& (CreatedLocalTime+1 7 AM)
return CreatedLocalTime date with DD/MM/YYYY format
On other words, today production = sum of yesterday from 7 AM till today at 7 AM.
Any help using case?
For day 7AM to day+1 7AM, you can try:
SELECT CAST(CreatedLocalTime as date)
...
FROM ...
WHERE ...
CreatedLocalTime >= DATEADD(hour, 7, CAST(CAST(CreatedLocalTime as date) as datetime))
AND
CreatedLocalTime < DATEADD(hour, 31, CAST(CAST(CreatedLocalTime as date) as datetime))
...
For previous day 7AM to day 7AM, replace 7 by -14 and 31 by 7.
Another way..
SELECT CASE WHEN CreatedLocalTime BETWEEN DATEADD(HOUR, 7,
CAST(CAST (CreatedLocalTime AS DATE) AS DATETIME))
AND DATEADD(HOUR, 31,
CAST(CAST (CreatedLocalTime AS DATE) AS DATETIME))
THEN REPLACE(CONVERT(NVARCHAR, CreatedLocalTime, 103), ' ', '/')
END AS CreatedLocalTime
You can write the else part for this, if needed
It looks like you want somthing along the lines of
DECLARE #StartDateTime Datetime
DECLARE #EndDateTime Datetime
SET #EndDateTime = DATEADD(hour, 7,convert(datetime,convert(date,getdate())) )
SET #StartDateTime = DATEADD(day, -1, #EndDateTime )
--Print out the variables for demonstration purposes
PRINT '#StartDateTime = '+CONVERT(nchar(19), #StartDateTime,120)
PRINT '#EndDateTime = '+CONVERT(nchar(19), #EndDateTime,120)
SELECT SUM (Production) AS Prod_Date FROM YourSchema.YourTable WHERE CreatedLocalTime >= #StartDateTime AND CreatedLocalTime < #EndDateTime
But you could also look at it as all the times which after you remove 7 hours from them are yesterday
SELECT SUM (Production) AS Prod_Date
FROM YourSchema.YourTable
WHERE DATEDIFF(day,DATEADD(hour, -7, CreatedLocalTime ))) = 1
The First version will be more efficient as the query will only have to do the date arithmetic once at the start while the second involved executing DATEDIFF and DATEADD for every record. This will be slower on large amounts of data.
The Gold plated solution would be to add a computed column to your table
ALTER TABLE YourSchema.YourTable ADD EffectiveDate AS CONVERT(date, DATEDIFF(day,DATEADD(hour, -7, CreatedLocalTime ))))
And then an index on that column
CREATE INDEX IX_YourTable_EffectiveDate ON YourSchema.YourTable (EffectiveDate )
So you can write
DECLARE #YesterDay date = DATEADD(day,-1, getdate())
SELECT SUM (Production) AS Prod_Date
FROM YourSchema.YourTable
WHERE EffectiveDate = #YesterDay

Get yesterdays date and if Monday get weekend range for SQL server

How do I get yesterdays date and if the current date is Monday I would need Sunday, Saturday and Friday. This is already asked here for ms access. I now need this for SQL server. How would I go about this?
Will create an inline view that will return the previous date in SQL It will return between 1 and 3 rows depending on the current date.
If current date is Monday Return:
Sundays date
Saturdays date
Fridays date
If current date is Tuesday then Return: Mondays date
If current date is Wednesday then Return: Tuesdays date
If current date is Thursday then Return: Wednesdays date
If current date is Friday then Return: Thursdays date
If current date is Saturday then Return: Fridays date
If current date is Sunday then Return: Saturdays date
I hope this helps explain what I am trying to do more clearly.
sample select query
--get previous date
select * from [Purchase Orders] where MyDate in (previous date(s))
Not entirely clear about the question though. But you can do something on the similar lines.
Using DATEPART and DATEADD
DECLARE #TodaysDate DATETIME
SET #TodaysDate = '2013-04-10'
SELECT CASE
WHEN DATEPART (DW, DATEADD (DD, -1, #TodaysDate )) IN (1, 6, 7)
THEN 'WeekEnd' ELSE 'WeekDay'
END D
Using the query you linked to, you can try the code below:
SELECT *
FROM [Purchase Order]
WHERE MyDate >= CASE
WHEN DATENAME(dw, CONVERT(CHAR(8), GETDATE() , 112)) LIKE 'Monday' THEN CONVERT(CHAR(8), DATEADD(dd, -3, GETDATE()), 112)
ELSE CONVERT(CHAR(8), DATEADD(dd, -1, GETDATE()), 112)
END
AND MyDate < CONVERT(CHAR(8),GETDATE(),112)
You can use the following table function:
CREATE FUNCTION dbo.ufnPreviousDay (#suppliedDate DATE)
RETURNS #PreviousDates TABLE (PreviousDate DATE)
AS
BEGIN
INSERT INTO #PreviousDates (
PreviousDate)
SELECT
PreviousDate = DATEADD(DAY, -1, #suppliedDate)
IF DATEPART(WEEKDAY, DATEADD(DAY, ##DATEFIRST - 1, #suppliedDate)) = 1 -- If Monday
BEGIN
INSERT INTO #PreviousDates (
PreviousDate)
SELECT
PreviousDate = DATEADD(DAY, -2, #suppliedDate)
UNION ALL
SELECT
PreviousDate = DATEADD(DAY, -3, #suppliedDate)
END
RETURN
END
You can use it like this:
SELECT
T.*
FROM
dbo.ufnPreviousDay('2018-03-19') AS T
/*
Result:
2018-03-18
2018-03-17
2018-03-16
*/
If you want today's previous dates:
SELECT
T.*
FROM
YourTable AS T
INNER JOIN dbo.ufnPreviousDay(GETDATE()) AS M ON T.MyDate = M.PreviousDate

Group SUM data in 24 hour chunks

I have data in Microsoft SQL Server 2008 that I need to SUM. The catch is I need to group the sums by a 24 hour period. The 24 hour period is from 3:00pm one day to 3:00pm the next day.
For Example
DateExited, Value
1/1/2012 15:00, 5
1/1/2012 15:04, 6
1/1/2012 17:00, 7
1/2/2012 00:00, -5
1/2/2012 09:00, 10
1/2/2012 15:00, 31
The sum of that should be 54. I have the following query but that groups everything from midnight to midnight instead of 3:00 pm to 3:00 pm
SELECT dateadd(day,datediff(day,0, dateadd(hh, 0, DateExited) ),0) As SummaryDate, SUM(Value) as s1
FROM Test
where DateExited BETWEEN dateadd(year,datediff(year,0,GETDATE()),0) AND GetDate()
GROUP BY dateadd(day,datediff(day,0, dateadd(hh, 0, DateExited) ),0)
ORDER BY SummaryDate
You could add minus 15 hours, and then cast the result to date:
select cast(dateadd(hour,-15,'2012-05-06 14:30') as date) -- 2012-05-05
select cast(dateadd(hour,-15,'2012-05-06 15:30') as date) -- 2012-05-06
Giving you a group by like:
group by cast(dateadd(hour,-15,'2012-05-06 03:30') as date)
Subtract 15 hours from your date/time value should give you the results you are looking for.
Also, with SQL 2008, you can convert datetimes to dates instead of adding days to 0.
SELECT CONVERT(DATE, DATEADD(hour, -15, DateExited)) As SummaryDate, SUM(Value) as s1
FROM Test
WHERE DATEADD(hour, -15, DateExited) BETWEEN #StartDate AND #EndDate
GROUP BY CONVERT(DATE, DATEADD(hour, -15, DateExited))
ORDER BY SummaryDate
The easiest way is to cast to date:
SELECT cast(SummaryDate as date), SUM(Value) as s1
FROM Test
where DateExited BETWEEN dateadd(year,datediff(year,0,GETDATE()),0) AND GetDate()
GROUP BY cast(SummaryDate as date)
ORDER BY 1
You could create a function to return the needed value given an date input parameter:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION GetValueSum
(
#StartDate DATETIME
)
RETURNS INT
AS
BEGIN
DECLARE #ValueSum INT
DECLARE #StartDateTime DATETIME
DECLARE #EndDateTime DATETIME
-- Set the starting time to 3 PM on the datetime sent in:
SET #StartDateTime = DATEADD(hh, 15, CAST(CAST(#StartDate AS DATETIME) AS DATETIME))
-- Set the end time to one day later, minus 3 milliseconds (this smallest unit sql server can use)
SET #EndDateTime = DATEADD(ms, -3, DATEADD(dd, 1, #StartDateTime))
SELECT #ValueSum = SUM(Value)
FROM dbo.test
WHERE DateExited BETWEEN #StartDateTime AND #EndDateTime
RETURN #ValueSum
END
GO

Group days by week

Is there is a way to group dates by week of month in SQL Server?
For example
Week 2: 05/07/2012 - 05/13/2012
Week 3: 05/14/2012 - 05/20/2012
but with Sql server statement
I tried
SELECT SOMETHING,
datediff(wk, convert(varchar(6), getdate(), 112) + '01', getdate()) + 1 AS TIME_
FROM STATISTICS_
GROUP BY something, TIME_
ORDER BY TIME_
but it returns the week number of month. (means 3)
How to get the pair of days for current week ?
For example, now we are in third (3rd) week and I want to show 05/14/2012 - 05/20/2012
I solved somehow:
SELECT DATEADD(ww, DATEDIFF(ww,0,<my_column_name>), 0)
select DATEADD(ww, DATEDIFF(ww,0,<my_column_name>), 0)+6
Then I will get two days and I will concatenate them later.
All right, bear with me here. We're going to build a temporary calendar table that represents this month, including the days from before and after the month that fall into your definition of a week (Monday - Sunday). I do this in a lot of steps to try to make the process clear, but I probably haven't excelled at that in this case.
We can then generate the ranges for the different weeks, and you can join against your other tables using that.
SET DATEFIRST 7;
SET NOCOUNT ON;
DECLARE #today SMALLDATETIME, #fd SMALLDATETIME, #rc INT;
SELECT #today = DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0), -- today
#fd = DATEADD(DAY, 1-DAY(#today), #today), -- first day of this month
#rc = DATEPART(DAY, DATEADD(DAY, -1, DATEADD(MONTH, 1, #fd)));-- days in month
DECLARE #thismonth TABLE (
[date] SMALLDATETIME,
[weekday] TINYINT,
[weeknumber] TINYINT
);
;WITH n(d) AS (
SELECT TOP (#rc+12) DATEADD(DAY, ROW_NUMBER() OVER
(ORDER BY [object_id]) - 7, #fd) FROM sys.all_objects
)
INSERT #thismonth([date], [weekday]) SELECT d, DATEPART(WEEKDAY, d) FROM n;
DELETE #thismonth WHERE [date] < (SELECT MIN([date]) FROM #thismonth WHERE [weekday] = 2)
OR [date] > (SELECT MAX([date]) FROM #thismonth WHERE [weekday] = 1);
;WITH x AS ( SELECT [date], weeknumber, rn = ((ROW_NUMBER() OVER
(ORDER BY [date])-1) / 7) + 1 FROM #thismonth ) UPDATE x SET weeknumber = rn;
-- now, the final query given all that (I've only broken this up to get rid of the vertical scrollbars):
;WITH ranges(w,s,e) AS (
SELECT weeknumber, MIN([date]), MAX([date]) FROM #thismonth GROUP BY weeknumber
)
SELECT [week] = CONVERT(CHAR(10), r.s, 120) + ' - ' + CONVERT(CHAR(10), r.e, 120)
--, SOMETHING , other columns from STATISTICS_?
FROM ranges AS r
-- LEFT OUTER JOIN dbo.STATISTICS_ AS s
-- ON s.TIME_ >= r.s AND s.TIME_ < DATEADD(DAY, 1, r.e)
-- comment this out if you want all the weeks from this month:
WHERE w = (SELECT weeknumber FROM #thismonth WHERE [date] = #today)
GROUP BY r.s, r.e --, SOMETHING
ORDER BY [week];
Results with WHERE clause:
week
-----------------------
2012-05-14 - 2012-05-20
Results without WHERE clause:
week
-----------------------
2012-04-30 - 2012-05-06
2012-05-07 - 2012-05-13
2012-05-14 - 2012-05-20
2012-05-21 - 2012-05-27
2012-05-28 - 2012-06-03
Note that I chose YYYY-MM-DD on purpose. You should avoid regional formatting like M/D/Y especially for input but also for display. No matter how targeted you think your audience is, you're always going to have someone who thinks 05/07/2012 is July 5th, not May 7th. With YYYY-MM-DD there is no ambiguity whatsoever.
Create a calendar table, then you can query week numbers, first/last days of specific weeks and months etc. You can also join on it queries to get a date range etc.
How about a case statement?
case when datepart(day, mydatetime) between 1 and 7 then 1
when datepart(day, mydatetime) between 8 and 14 then 2
...
You'll also have to include the year & month unless you want all the week 1s in the same group.
It's not clear of you want to "group dates by week of month", or alternately "select data from a given week"
If you mean "group" this little snippet should get you 'week of month':
SELECT <stuff>
FROM CP_STATISTICS
WHERE Month(<YOUR DATE COL>) = 5 --april
GROUP BY Year(<YOUR DATE COL>),
Month(<YOUR DATE COL>),
DATEDIFF(week, DATEADD(MONTH, DATEDIFF(MONTH, 0, <YOUR DATE COL>), 0)
, <YOUR DATE COL>) +1
Alternately, if you want "sales for week 1 of April, ordered by date" You could do something like..
DECLARE #targetDate datetime2 = '5/3/2012'
DECLARE #targetWeek int = DATEDIFF(week, DATEADD(MONTH,
DATEDIFF(MONTH, 0, #targetDate), 0), #targetDate) +1
SELECT <stuff>
FROM CP_STATISTICS
WHERE MONTH(#targetDate) = Month(myDateCol) AND
YEAR(#targetDate) = Year (myDateCol) AND
#targetWeek = DATEDIFF(week, DATEADD(MONTH,
DATEDIFF(MONTH, 0, myDateCol), 0), myDateCol) +1
ORDER BY myDateCol
Note, things would get more complicated if you use non-standard weeks, or want to reach a few days into an earlier month for weeks that straddle a month boundary.
EDIT 2
From looking at your 'solved now' section. I think your question is "how do I get data out of a table for a given week?"
Your solution appears to be:
DECLARE #targetDate datetime2 = '5/1/2012'
DECLARE #startDate datetime2 = DATEADD(ww, DATEDIFF(ww,0,targetDate), 0)
DECLARE #endDate datetime2 = DATEADD(ww, DATEDIFF(ww,0,#now), 0)+6
SELECT <stuff>
FROM STATISTICS_
WHERE dateStamp >= #startDate AND dateStamp <= #endDate
Notice how if the date is 5/1 this solution results in a start date of '4/30/2012'. I point this out because your solution crosses month boundaries. This may or may not be desirable.

Getting Number of weeks in a Month from a Datetime Column

I have a table called FcData and the data looks like:
Op_Date
2011-02-14 11:53:40.000
2011-02-17 16:02:19.000
2010-02-14 12:53:40.000
2010-02-17 14:02:19.000
I am looking to get the Number of weeks in That Month from Op_Date. So I am looking for output like:
Op_Date Number of Weeks
2011-02-14 11:53:40.000 5
2011-02-17 16:02:19.000 5
2010-02-14 12:53:40.000 5
2010-02-17 14:02:19.000 5
This page has some good functions to figure out the last day of any given month: http://www.sql-server-helper.com/functions/get-last-day-of-month.aspx
Just wrap the output of that function with a DATEPART(wk, last_day_of_month) call. Combining it with an equivalent call for the 1st-day-of-week will let you get the number of weeks in that month.
Use this to get the number of week for ONE specific date. Replace GetDate() by your date:
declare #dt date = cast(GetDate() as date);
declare #dtstart date = DATEADD(day, -DATEPART(day, #dt) + 1, #dt);
declare #dtend date = dateadd(DAY, -1, DATEADD(MONTH, 1, #dtstart));
WITH dates AS (
SELECT #dtstart ADate
UNION ALL
SELECT DATEADD(day, 1, t.ADate)
FROM dates t
WHERE DATEADD(day, 1, t.ADate) <= #dtend
)
SELECT top 1 DatePart(WEEKDAY, ADate) weekday, COUNT(*) weeks
FROM dates d
group by DatePart(WEEKDAY, ADate)
order by 2 desc
Explained: the CTE creates a result set with all dates for the month of the given date. Then we query the result set, grouping by week day and count the number of occurrences. The max number will give us how many weeks the month overlaps (premise: if the month has 5 Mondays, it will cover five weeks of the year).
Update
Now, if you have multiple dates, you should tweak accordingly, joining your query with the dates CTE.
Here is my take on it, might have missed something.
In Linq:
from u in TblUsers
let date = u.CreateDate.Value
let firstDay = new DateTime(date.Year, date.Month, 1)
let lastDay = firstDay.AddMonths(1)
where u.CreateDate.HasValue
select Math.Ceiling((lastDay - firstDay).TotalDays / 7)
And generated SQL:
-- Region Parameters
DECLARE #p0 Int = 1
DECLARE #p1 Int = 1
DECLARE #p2 Float = 7
-- EndRegion
SELECT CEILING(((CONVERT(Float,CONVERT(BigInt,(((CONVERT(BigInt,DATEDIFF(DAY, [t3].[value], [t3].[value2]))) * 86400000) + DATEDIFF(MILLISECOND, DATEADD(DAY, DATEDIFF(DAY, [t3].[value], [t3].[value2]), [t3].[value]), [t3].[value2])) * 10000))) / 864000000000) / #p2) AS [value]
FROM (
SELECT [t2].[createDate], [t2].[value], DATEADD(MONTH, #p1, [t2].[value]) AS [value2]
FROM (
SELECT [t1].[createDate], CONVERT(DATETIME, CONVERT(NCHAR(2), DATEPART(Month, [t1].[value])) + ('/' + (CONVERT(NCHAR(2), #p0) + ('/' + CONVERT(NCHAR(4), DATEPART(Year, [t1].[value]))))), 101) AS [value]
FROM (
SELECT [t0].[createDate], [t0].[createDate] AS [value]
FROM [tblUser] AS [t0]
) AS [t1]
) AS [t2]
) AS [t3]
WHERE [t3].[createDate] IS NOT NULL
According to this MSDN article: http://msdn.microsoft.com/en-us/library/ms174420.aspx you can only get the current week in the year, not what that month returns.
There may be various approaches to implementing the idea suggested by #Marc B. Here's one, where no UDFs are used but the first and the last days of month are calculated directly:
WITH SampleData AS (
SELECT CAST('20110214' AS datetime) AS Op_Date
UNION ALL SELECT '20110217'
UNION ALL SELECT '20100214'
UNION ALL SELECT '20100217'
UNION ALL SELECT '20090214'
UNION ALL SELECT '20090217'
),
MonthStarts AS (
SELECT
Op_Date,
MonthStart = DATEADD(DAY, 1 - DAY(Op_Date), Op_Date)
/* alternatively: DATEADD(MONTH, DATEDIFF(MONTH, 0, Op_Date), 0) */
FROM FcData
),
Months AS (
SELECT
Op_Date,
MonthStart,
MonthEnd = DATEADD(DAY, -1, DATEADD(MONTH, 1, MonthStart))
FROM FcData
)
Weeks AS (
SELECT
Op_Date,
StartWeek = DATEPART(WEEK, MonthStart),
EndWeek = DATEPART(WEEK, MonthEnd)
FROM MonthStarts
)
SELECT
Op_Date,
NumberOfWeeks = EndWeek - StartWeek + 1
FROM Weeks
All calculations could be done in one SELECT, but I chose to split them into steps and place every step in a separate CTE so it could be seen better how the end result was obtained.
You can get number of weeks per month using the following method.
Datepart(WEEK,
DATEADD(DAY,
-1,
DATEADD(MONTH,
1,
DATEADD(DAY,
1 - DAY(GETDATE()),
GETDATE())))
-
DATEADD(DAY,
1 - DAY(GETDATE()),
GETDATE())
+1
)
Here how you can get accurate amount of weeks:
DECLARE #date DATETIME
SET #date = GETDATE()
SELECT ROUND(cast(datediff(day, dateadd(day, 1-day(#date), #date), dateadd(month, 1, dateadd(day, 1-day(#date), #date))) AS FLOAT) / 7, 2)
With this code for Sep 2014 you'll get 4.29 which is actually true since there're 4 full weeks and 2 more days.