SQL Server 2012 - Select queries leap year - sql-server

I have a little issue with one my queries. The entire query is actually is a little long since it includes a UNION ALL.
SELECT 'ITV' = CASE WHEN tblIntake.StaffID Is Null THEN '<Unknown>' ELSE
(tblStaffMember.StaffLast + ', ' + tblStaffMember.StaffFirst + CASE WHEN
tblStaffMember.StaffMI Is Null THEN '' ELSE ' ' + tblStaffMember.StaffMI END) END,
tblMember.[LAST], tblMember.[FIRST],
'DueDate' = DATEADD(m, 6,CAST(CONVERT(Varchar(10),
MONTH(tblIntake.EnrollDate)) + '/' + CONVERT(Varchar(10),
DAY(tblIntake.EnrollDate)) + '/' + CONVERT(Varchar(10),YEAR(GETDATE()))As
DateTime)), 'Type' = '6 Month Appt'
From tblIntake LEFT JOIN tblStaffMember ON tblIntake.StaffID =
tblStaffMember.StaffID LEFT JOIN tblMember ON
tblIntake.KEY = tblMember.KEY
Where tblIntake.UnEnrollDate Is Null AND
DATEADD(m,6,CAST(CONVERT(Varchar(10),MONTH(tblIntake.EnrollDate)) + '/' +
CONVERT(Varchar(10),DAY(tblIntake.EnrollDate)) + '/' +
CONVERT(Varchar(10),YEAR(GETDATE()))As DateTime)) > GETDATE() AND
DATEADD(m, 6,CAST(CONVERT(Varchar(10),MONTH(tblIntake.EnrollDate)) + '/' +
CONVERT(Varchar(10),DAY(tblIntake.EnrollDate)) + '/' +
CONVERT(Varchar(10),YEAR(GETDATE()))As DateTime)) <= DATEADD(d, 45, GETDATE())
So, I have this wonderful query. Everything was running okay until a user entered a leap year date for ENROLLDATE in tblIntake. How would I go about fixing it? My other UNION does the same SELECT statements with the exception of for when it does
CONVERT(VARCHAR(10),YEAR(GetDate()-1)) as DateTime > '4th line from the bottom
CONVERT(VARCHAR(10),YEAR(GetDate()-1)) as DateTime > '2nd line from the bottom
EDIT:
Receiving this error when I run the query
Msg 242, Level 16, State 3, Line 1
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
I tried running the separate queries, and it seems like I'm only getting the error when I do this..
CONVERT(VARCHAR(10),YEAR(GetDate()-1)) as DateTime > '4th line from the bottom
CONVERT(VARCHAR(10),YEAR(GetDate()-1)) as DateTime > '2nd line from the bottom
After UNION ALL
EDIT 2:
I've been working off Sean's answer which makes more sense. Here is the code that I've got....
SELECT 'CSC' = case when tblIntake.staffID is null Then '<notIndicated>' Else (tblStaffMember.staffLast + ',' + tblStaffMember.StaffFirst + case when tblStaffMember.staffMI is null then '' else ' ' + tblStaffMember.staffMI END)end
, tblMember.[Last], tblMember.[First]
,'Due' = DateADD(m,6,cast(tblIntake.enrolldate as datetime))
,'Type' = '6 Month Review'
from tblMembEnrollment
left join tblStaffMember on tblIntake.staffID = tblStaffMember.staffID
left join tblMember on tblIntake.SBkey=tblMember.sbkey
where tblIntake.unEnrollDate is null and dateAdd(m, 6, tblIntake.enrolldate) > GETDATE()
and dateadd(m, 6, cast(tblIntake.enrolldate as DateTime))<= DateAdd(d,45,GetDate())
The issue I'm seeing is that in the old query, when the code takes apart the EnrollDate into days, months and years for years it used GET DATE, see below in between *** ****
Where tblIntake.UnEnrollDate Is Null AND
DATEADD(m,6,CAST(CONVERT(Varchar(10),MONTH(tblIntake.EnrollDate)) + '/' +
CONVERT(Varchar(10),DAY(tblIntake.EnrollDate)) + '/' +
CONVERT(Varchar(10),***YEAR(GETDATE()))As DateTime))*** > GETDATE()
Now it was easier done this way since he did take it apart, how is it that I can do it with my full Enroll date.

If I understand what you are trying to do here you can greatly simplify this. Please note that I used aliases everywhere instead of repeating the table name over and over. Also, I used the datepart names instead of the abbreviations as they are much more clear. Last but not least I just used the existing datetime value. I converted them to the date datatype as what it appears the existing logic is doing is converting it to a date value to avoid the time portion. This as fairly common prior to 2005 when the date datatype was added. I also reduced all the nested case expressions into something much easier to read.
SELECT 'ITV' = ISNULL(sm.StaffLast + ', ' + sm.StaffFirst + ISNULL(' ' + sm.StaffMI, ''), '<Unknown>')
, tblMember.[LAST]
, tblMember.[FIRST]
, 'DueDate' = DATEADD(month, 6, convert(date, tblIntake.EnrollDate))
, 'Type' = '6 Month Appt'
From tblIntake i
LEFT JOIN tblStaffMember sm ON i.StaffID = sm.StaffID
LEFT JOIN tblMember m ON i.KEY = m.KEY
Where i.UnEnrollDate Is Null
AND DATEADD(month, 6, convert(date, i.EnrollDate)) > GETDATE()
AND DATEADD(month, 6, convert(date, i.EnrollDate)) <= DATEADD(day, 45, GETDATE())
--EDIT--
With the clarity of rules I think this should be what you are looking for. This has the advantage of also being SARGable so that any index on i.EnrollDate can be utilized.
Where i.UnEnrollDate Is Null
AND convert(date, i.EnrollDate) > DATEADD(month, -6, GETDATE())
AND convert(date, i.EnrollDate) <= DATEADD(day, -45, GETDATE())

I'd replace all of those date parts and converts with dateadd, something like:
declare #test datetime
set #test = '2-29-2016'
select cast(#test as varchar(11))
, cast(dateadd(mm, 6, #test) as varchar(11))
, cast(dateadd(yy, -1, #test) as varchar(11))
If you keep the dates as datetimes, SQL server will automatically correct for leap years, shorter months, etc. The query above returns:
Feb 29 2016 Aug 29 2016 Feb 28 2015

Related

Format function is not working at where clause to filter the format date?

Getting the months list of current year and Previous year
SELECT FORMAT(DATEADD(month,number,CAST(YEAR(DATEADD(YEAR,-1,GETDATE())) AS varchar(4)) + '-01-01'),'MMM') + '-' +
SUBSTRING(CAST(CAST(YEAR(GETDATE()) AS VARCHAR(4)) + IIF(number<12,-1,0) AS VARCHAR(4)),3,2) as Months into #temptable
FROM master..spt_values
WHERE type = 'P'
AND number < 24
Expected Output:-1
From Current Month- Mar-19
Feb-19
End of CurrentYear Month -Jan-19
ExpectedOutPut:2
Jan-18
to
Dec -18
I'm trying this query
select *from #temptable where Months>=FORMAT(DATEADD(yy, DATEDIFF(yy, 0, getdate()), 0),'MMM-yy') and Months<=FORMAT(DATEADD(mm, DATEDIFF(mm, 0, getdate()), 0),'MMM-yy')
select *from #temptable where Months>=FORMAT(DATEADD(yy, DATEDIFF(yy, 0, getdate())-1, 0),'MMM-yy') and Months<= FORMAT(DATEADD(yy, DATEDIFF(yy, 0, getdate()), -1),'MMM-yy')
Seeing as you are essentially storing your month/ years as text, to actually compare them to dates is painful at best. You would be much better storing either real dates, or years/ months as two separate values, maybe with a text version as well for display purposes?
Anyway, based on your poor data model you could do this to get what you need:
SELECT * FROM #temptable WHERE YEAR(CONVERT(DATE, '01-' + Months)) = YEAR(GETDATE()) - 1;
SELECT * FROM #temptable WHERE YEAR(CONVERT(DATE, '01-' + Months)) = YEAR(GETDATE()) AND MONTH(CONVERT(DATE, '01-' + Months)) <= MONTH(GETDATE());
But note that this now introduces a dependency on your regional format, as this wouldn't work in America (for example) as day comes after month. You would be far better using ANSI date format of YYYYMMDD (or storing the dates as year/ months, or hey(!) even as dates).

SQL Server Unable to convert a string to a date in a where clause (Code 241)

I have a query which cut a substring out of a char field and returns it a a date.
And it works:
select
ujp_jobid, ujp_lfdnr,
isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date, getDate())) para_date,
datediff(day, isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date,getDate())), convert(date,getDate())) datedif
from
uno_jobpara
where
ujp_jobid between 0 and 30000
and ujp_paraname = 'P_PGENDE'
The result is:
1 6 2017-11-28 8
2 372 2017-05-06 214
3 84 2017-05-01 219
...
I first tried the to use the datedif part as where clause:
...
and ujp_paraname = 'P_PGENDE'
and datediff(day, isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date,getDate()) ), convert(date,getDate())) > 0
Suddenly the server raised an Error:
[Code: 241, SQL State: S0001] Fehler beim Konvertieren einer Zeichenfolge in ein Datum und/oder eine Uhrzeit.
(rough translation: Error converting a string to a date and/or a time)
Not quite sure why this is, but I guessed, that there the server tries to check the where conditional first and thinks that it might run into an an error.
However I tried to put in all in another select:
select
ujp_jobid, ujp_lfdnr, para_date, datedif
from
(select
ujp_jobid, ujp_lfdnr,
isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date,getDate()) ) para_date,
datediff(day, isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date, getDate()) ), convert(date, getDate())) datedif
from
uno_jobpara
where
ujp_jobid between 0 and 30000
and ujp_paraname = 'P_PGENDE') as tt
where
tt.datedif > 0;
The same error?! Why, and how can I tell SQL Server to run a subquery first? Do I really need a temp table?
TIA
Jo
First check if all parsed strings can be converted to DATE.
Since you are using SQL Server 2016, you can use TRY_CONVERT to test if you can convert them or not.
SET DATEFORMAT dd.mm.yyyy; -- This format is equivalent to format 104
SELECT
ujp_jobid, ujp_lfdnr,
, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1, 10)
WHERE
TRY_CONVERT(DATE, SUBSTRING(ujp_parawert, CHARINDEX(' ', ujp_parawert) + 1,10)) IS NULL
Check the records you get, those records cannot be converted.
If you get any, you have to decide if NULLs are acceptable or not.
If they are, use TRY_CONVERT() instead of CONVERT/CAST
If NULL are not acceptable, you'll have to modify your expression to handle all possible variations.
DATEFROMPARTS(year, month, day) can be useful too if you have to modify the expression.
This doesn't look like something to be solved with a temp table.
Firstly I'd avoid using convert(date,getdate()) because it converts the getdate() into a string and back again, hoping that the formats fit. I'd use cast(getdate() as date).
Secondly the issue should happen in your inner query, too, if you really scroll down to the end.
You could test whether the substring is valid with a like '[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]'
Regards, Manfred

Check if date falls within Month and Year range

If a user selects a range such as:
Start: November 2016
End: September 2017,
I want to include all results that fall within the range of 2016-11-01 to 2017-09-30.
I tried concatenating together the year, month, and day, however the issue comes that not all months have the same last day. While I know all months start on day 01, a month's end day can be 28, 29, 30, or 31.
Is there a way to do this without constructing the date? SqlServer 2008 doesn't have the EOMONTH function, and I feel like anything more complex than that is not the right solution. I would like to avoid this:
WHERE
DateCol >= '2016' + '-' + '11' + '-01' AND
DateCol <= '2017' + '-' + '09' + '-30'
It really seems to me that the easiest and best answer is to go from the first of the beginning month to the first of the month after the ending month, and make the second comparison not inclusive.
In other words, instead of this:
WHERE
DateCol >= '2016' + '-' + '11' + '-01' AND
DateCol <= '2017' + '-' + '09' + '-30'
simply this:
WHERE
DateCol >= '2016' + '-' + '11' + '-01' AND
DateCol < '2017' + '-' + '10' + '-01'
There is a faster way to do so :
DECLARE #minDate DATE
DECLARE #maxDate DATE
SET #minDate = XXXXX
SET #maxDate = YYYYY
-- Get the first day of the month minDate.
SET #minDate = CONVERT(datetime,CONVERT(varchar(6),#minDate,112)+'01',112)
-- Get the last day of the month minDate.
SET #maxDate = CONVERT(datetime,CONVERT(varchar(6),#maxDate,112)+'01',112)
SET #maxDate = DATEADD(day, -1, DATEADD(month, 1, #maxDate))
SELECT * FROM myTABLE WHERE DateCol >= #minDate AND DateCol <= #maxDate
Or :
SELECT * FROM myTABLE
WHERE DateCol >= CONVERT(datetime,CONVERT(varchar(6),XXXXX,112)+'01',112)
AND DateCol <= DATEADD(day, -1, DATEADD(month, 1, CONVERT(datetime,CONVERT(varchar(6),YYYYY,112)+'01',112)))
Use syntax like CONVERT(datetime,'20170930',112) or CONVERT(datetime,'09-30-2017',110) for XXXXX and YYYYY rather than '2017-09-30' that use SQL Server implicit convertion from char to datetime (rely on the server configuration : can be hazardous!!!)).
Using this syntax is faster because #minDate and #maxDate do not need any evaluation. So that indexes can be used directly...
Otherwise a scalar function that will simulate the eomonth() behaviour could be usefull...
You could use following select statement to get last date of any month (and any year) by passing a field or date to it:
DECLARE #dtDate DATE
SET #dtDate = '09/25/2016'
SELECT CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#dtDate)+1,0)) AS DATE) AS LastDay_AnyMonth
Please provide some example data and desired result and I will update my answer further.
Here you go:
DECLARE #YourTable TABLE (YourData DATE);
INSERT INTO #YourTable VALUES
('2016-11-01'),
('2016-09-05'),
('2017-03-03'),
('2017-11-11'),
('2017-12-14'),
('2017-09-30');
WITH CTE AS (
SELECT YourData
FROM #YourTable
WHERE YEAR(YourData) =2016 AND MONTH (YourData) >= 11
)
SELECT YourData
FROM #YourTable
WHERE YEAR(YourData) =2017 AND MONTH (YourData) <= 9
UNION ALL
SELECT YourData
FROM CTE;
There is no need to know the end of the month (28 or 30 or 31).
For 2008, you can simply convert the string
Example
Select Date1=convert(date,'November 2016')
,Date2=dateadd(DAY,-1,dateadd(MONTH,1,convert(date,'September 2017')))
Returns
Date1 Date2
2016-11-01 2017-09-30
So the WHERE would be somthing like this
...
Where DateCol between convert(date,'November 2016')
and dateadd(DAY,-1,dateadd(MONTH,1,convert(date,'September 2017')))
A useful construct for performing date-based operations is to make use of a Date Dimension table. You are creating a lookup table that is populated with a lot of information about dates over a large span of time. You can then query the table based on the information that you do have. The table is small enough so that it does not impose significant performance concerns.
In your particular case, you have the month and year. You would plug that into the date dimension table to get the first of the month from the beginning month and the last of the month from the ending month. You now have a time range to search over without any complex logic or calculations on the fly.
Aaron Bertrand explains it in depth here: https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/

Convert Date Stored as NUMERIC to DATETIME

I am currently working on a query that needs to calculate the difference in days between two different dates. I've had issues with our DATE columns before, because they are all being stored as numeric columns which is a complete pain.
I tried using CONVERT as I had done in the past to try and get the different pieces of the DATETIME string built, but I am not having any luck.
The commented line --convert(datetime,) is where I am having the issue. Basically, I need to convert PO_DATE and LINE_DOCK_DATE to a format that is usable, so I can calculate the difference between the two in days.
USE BWDW
GO
SELECT
[ITEM_NO]
,[ITEM_DESC]
,[HEADER_DUE_DATE]
,[BWDW].[dbo].[DS_tblDimWhs].WHS_SHORT_NAME AS 'Warehouse'
,[BWDW].[dbo].[DS_tblFactPODtl].[PO_NO] AS 'PO NUMBER'
,[BWDW].[dbo].[DS_tblFactPODtl].[PO_DATE] AS 'Start'
,[BWDW].[dbo].[DS_tblFactPODtl].[PO_STATUS] AS 'Status'
,[BWDW].[dbo].[DS_tblFactPODtl].[LINE_DOCK_DATE] AS 'End'
--,(SELECT CONVERT(DATETIME, CONVERT(CHAR(8), [BWDW].[dbo].[DS_tblFactPODtl].[PO_DATE])) FROM dbo.DS_tblFactPODtl)
FROM [BWDW].[dbo].[DS_tblFactPODtl]
INNER JOIN [BWDW].[dbo].[DS_tblDimWhs] ON [BWDW].[dbo].[DS_tblFactPODtl].WAREHOUSE = [BWDW].[dbo].[DS_tblDimWhs].WAREHOUSE
INNER JOIN [BWDW].[dbo].[DS_tblFactPO] ON [BWDW].[dbo].[DS_tblFactPODtl].PO_NO = [BWDW]. [dbo].[DS_tblFactPO].PO_NO
WHERE [BWDW].[dbo].[DS_tblFactPODtl].[PO_STATUS] = 'Closed'
AND [BWDW].[dbo].[DS_tblFactPODtl].[LINE_DOCK_DATE] <> 0
I have a snippet I saved from a previous project I worked on that needed to only display results from today through another year. That had a bunch of CAST and CONVERTS in it, but I tried the same methodology with no success.
In the long run, I want to add a column to each database table to contain a proper datetime column that is usable in the future... but that is another story. I have read numerous posts on stackoverflow that talk about converting to NUMERIC and such, but nothing out of a NUMERIC back to DATETIME.
Example data:
Start | End | Difference
--------------------------------
20110501 | 20111019 | 171
20120109 | 20120116 | 7
20120404 | 20120911 | 160
Just trying to calculate the difference..
MODIFIED PER AARON:
SELECT
FPODtl.[ITEM_NO] AS [Item]
,FPODtl.[ITEM_DESC] AS [Description]
,D.WHS_SHORT_NAME AS [Warehouse]
,FPODtl.[PO_NO] AS [PO NUMBER]
,FPODtl.[PO_DATE] AS [Start]
,FPODtl.[PO_STATUS] AS [Status]
,FPODtl.[LINE_DOCK_DATE] AS [End]
,DATEDIFF
(
DAY,
CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.PO_DATE)) = 1
THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.PO_DATE)) END,
CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) = 1
THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) END
)
FROM [dbo].[DS_tblFactPODtl] AS FPODtl
INNER JOIN [dbo].[DS_tblDimWhs] AS D
ON FPODtl.WAREHOUSE = D.WAREHOUSE
INNER JOIN [dbo].[DS_tblFactPO] AS FPO
ON FPODtl.PO_NO = FPO.PO_NO
WHERE FPODtl.[PO_STATUS] = 'Closed'
AND FPODtl.[LINE_DOCK_DATE] <> 0;
DECLARE #x NUMERIC(10,0);
SET #x = 20110501;
SELECT CONVERT(DATETIME, CONVERT(CHAR(8), #x));
Result:
2011-05-01 00:00:00.000
To compare two:
DECLARE #x NUMERIC(10,0), #y NUMERIC(10,0);
SELECT #x = 20110501, #y = 20111019;
SELECT DATEDIFF
(
DAY,
CONVERT(DATETIME, CONVERT(CHAR(8), #x)),
CONVERT(DATETIME, CONVERT(CHAR(8), #y))
);
Result:
171
More importantly, fix the table. Stop storing dates as numbers. Store them as dates. If you get errors with this conversion, it's because your poor data choice has allowed bad data into the table. You can get around that - potentially - by writing the old version of TRY_CONVERT():
SELECT DATEDIFF
(
DAY,
CASE WHEN ISDATE(col1)=1 THEN CONVERT(DATETIME, col1) END,
CASE WHEN ISDATE(col2)=1 THEN CONVERT(DATETIME, col2) END
)
FROM
(
SELECT
col1 = CONVERT(CHAR(8), col1),
col2 = CONVERT(CHAR(8), col2)
FROM dbo.table
) AS x;
This will produce nulls for any row where there is garbage in either column. Here is a modification to your original query:
SELECT
[ITEM_NO] -- what table does this come from?
,[ITEM_DESC] -- what table does this come from?
,[HEADER_DUE_DATE] -- what table does this come from?
,D.WHS_SHORT_NAME AS [Warehouse] -- don't use single quotes for aliases!
,FPODtl.[PO_NO] AS [PO NUMBER]
,FPODtl.[PO_DATE] AS [Start]
,FPODtl.[PO_STATUS] AS [Status]
,FPODtl.[LINE_DOCK_DATE] AS [End]
,DATEDIFF
(
DAY,
CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.PO_DATE)) = 1
THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.PO_DATE)) END,
CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) = 1
THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) END
)
FROM [dbo].[DS_tblFactPODtl] AS FPODtl
INNER JOIN [dbo].[DS_tblDimWhs] AS D
ON FPODtl.WAREHOUSE = D.WAREHOUSE
INNER JOIN [dbo].[DS_tblFactPO] AS FPO
ON FPODtl.PO_NO = FPO.PO_NO
WHERE FPODtl.[PO_STATUS] = 'Closed'
AND FPODtl.[LINE_DOCK_DATE] <> 0;
If the date stored as a number is like this: 20130226 for today, then the simpler way to convert to DATE or DATETIME would be:
SELECT CONVERT(DATETIME,CONVERT(VARCHAR(8),NumberDate),112)
Here is a quick formula to create a date from parts :
DateAdd( Month, (( #Year - 1900 ) * 12 ) + #Month - 1, #Day - 1 )
Simply use substrings from your original field to extract #Year, #Month and #Day. For instance, if you have a numeric like 19531231 for december 31th, 1953, you could do :
DateAdd( Month, (( SubString(Cast(DateField As Varchar(8)), 1, 4) - 1900 ) * 12 ) +
SubString(Cast(DateField As Varchar(8)), 5, 2) - 1,
SubString(Cast(DateField As Varchar(8)), 7, 2) - 1 )

select between years case when statement

I wrote a query
WITH sample AS (
SELECT CAST('2010-01-01' AS DATETIME) AS d
UNION ALL
SELECT DATEADD(dd, 1, i.vrp_notificationdate) as deneme
FROM Incident i
WHERE DATEADD(dd, 1, i.vrp_notificationdate) <= CAST('2011-11-01' AS DATETIME))
SELECT count(DATENAME(mm,l.vrp_notificationdate) +' '+DATENAME(yy,l.vrp_notificationdate)) as Toplam,DATENAME(mm,l.vrp_notificationdate) +' '+DATENAME(yy,l.vrp_notificationdate)
FROM Incident as l
group by
DATENAME(mm,l.vrp_notificationdate) +' '+DATENAME(yy,l.vrp_notificationdate)
the query show
10 November 2011
101 October 2011
4 September 2011
but i want to show this .
0 january 2010
0 february 2010
-
-
-
10 November 2011
101 October 2011
4 september 2011
0 december 2011
0 february 2011
i tried case when statement,but query show same result
How to solve what i use
Best regards.
You are trying to show data that doesn't exist. The idea of this solution is to
Add dummy dates
Assign a count of 0 to each dummy date
Union your original results with this dummy dates
Group into a final result
SQL Statement
DECLARE #StartDate DATE = '01-01-2010'
;WITH Dates(d) AS (
SELECT #StartDate
UNION ALL
SELECT DATEADD(mm, 1, d) AS Date
FROM Dates
WHERE d < '12-01-2012'
)
,WITH sample AS (
SELECT CAST('2010-01-01' AS DATETIME) AS d
UNION ALL
SELECT DATEADD(dd, 1, i.vrp_notificationdate) as deneme
FROM Incident i
WHERE DATEADD(dd, 1, i.vrp_notificationdate) <= CAST('2011-11-01' AS DATETIME)
)
SELECT SUM(Toplam) AS Toplam
, DateFormat
FROM (
SELECT COUNT(DATENAME(mm,l.vrp_notificationdate) + ' ' + DATENAME(yy,l.vrp_notificationdate)) AS Toplam
, DATENAME(mm,l.vrp_notificationdate) + ' ' + DATENAME(yy,l.vrp_notificationdate) AS DateFormat
, CONVERT(VARCHAR(6), l.vrp_notificationdate, 112) as orderDate
FROM Incident as l
GROUP BY
DATENAME(mm,l.vrp_notificationdate) + ' ' + DATENAME(yy,l.vrp_notificationdate)
, CONVERT(VARCHAR(6), l.vrp_notificationdate, 112)
UNION ALL
SELECT 0 AS Toplam
, DATENAME(mm, d) + ' ' + DATENAME(yy, d)
, CONVERT(VARCHAR(6), d.d, 112) as orderDate
FROM Dates d
) g
GROUP BY
DateFormat
ORDER BY
g.orderDate
Well, if the date doesn't appear, it means that there isn't any value present for that date. So, it's impossible to get that date to appear in the result.
To pass this the simplest solution is to:
Create a table with all the possible dates and another column that will start with zero.
Update that table with the results of the query that you made (update the column that start with zero to have the count values).
Display the end results from the new table:
select countValues + ' ' + dateValues from newTable
If you have any doubt, just ask :)
Why do you provide "WITH sample AS" when you do not use sample?
I'ld use this recursive query to build all dates for your result table.
WITH sample (d) AS (
SELECT CAST('2010-01-01' AS DATETIME)
UNION ALL
SELECT DATEADD(mm, 1, d) FROM sample WHERE DATEADD(mm, 1, d) <= CAST('2011-11-01' AS DATETIME)
)
select * from sample
You could then outer join this table with your Incident table to get the count of incidents for each month.
If you want to see a lot of months or even days, you might get an MSG 530 because of too much recursion. In this case you need the add OPTION (MAXRECURSION ) after "select * from sample".

Resources