Reputation: 4402
I have a stored procedure that accepts the following parameters:
Right now my query looks like this:
SELECT COL1, MyDate
FROM [dbo].[MyTable]
WHERE MONTH([MyDate]) >= @fromMonth
AND MONTH([MyDate]) <= @toMonth
AND YEAR([MyDate]) >= @fromYear
AND YEAR([MyDate]) <= @toYear
GROUP BY COL1, MyDate
But If I run the query with the parameters:
I get no results even if i have results that should be returned.
Upvotes: 0
Views: 89
Reputation: 82474
For sql server version 2012+, you can use DATEFROMPARTS
and EOMONTH
:
DECLARE @FromDate datetime, @ToDate datetime
SELECT @FromDate = DATEFROMPARTS(@fromYear, @FromMonth, 1),
@ToDate = EOMONTH(DATEFROMPARTS(@ToYear, @ToMonth, 1)),
SELECT COL1, MyDate
FROM [dbo].[MyTable]
WHERE [MyDate] >= @FromDate
AND [MyDate] <= @ToDate
GROUP BY COL1, MyDate
For versions before 2012, you can constract the date with a little math and casting:
DECLARE @FromDate datetime, @ToDate datetime
SELECT @FromDate = CAST(CAST(@FromYear * 10000 + @FromMonth * 100 + 1 as char(8)) as date),
@ToDate = DATEADD(MONTH, cast(CAST(@ToYear * 10000 + @ToMonth * 100 + 1 as char(8)) as date))
SELECT COL1, MyDate
FROM [dbo].[MyTable]
WHERE [MyDate] >= @FromDate
AND [MyDate] < @ToDate
GROUP BY COL1, MyDate
Note the use of DateAdd
to get the first day of the month after the @ToDate
and using <
and not <=
.
Upvotes: 4
Reputation: 2594
Since, you didn't give us some sample data from your table, I generated my own.
CREATE TABLE #Temp
(
MyCol VARCHAR(10)
, MyDate DATETIME
);
INSERT INTO #Temp
( MyCol, MyDate )
VALUES ( 'A', GETDATE() ),
( 'A', '2016-09-01' ),
( 'B', '2016-09-03' ),
( 'B', '2016-08-28' ),
( 'A', '2017-03-01' ),
( 'A', '2017-04-01' );
Let's take one date (2016-09-01
) and break it down.
Your WHERE
clause is effectively testing the following conditions for the first row.
9 >= 9
=> True9 <= 3
=> False2016 >= 2016
=> True2016 <= 2017
=> TrueBecause you're AND
-ing all of these conditions, you're not returning the results you're wanting.
You need to evaluate your values as dates rather than numbers, otherwise you'll encounter these issues.
You could do something like this:
DECLARE @ToDate AS DATE = CONVERT(DATE, CONVERT(VARCHAR, @toYear) + '-' + CONVERT(VARCHAR, @toMonth) + '-1');
DECLARE @FromDate AS DATE = CONVERT(DATE, CONVERT(VARCHAR, @fromYear) + '-' + CONVERT(VARCHAR, @fromMonth) + '-1');
SELECT t.MyCol
, t.MyDate
FROM #Temp AS t
WHERE t.MyDate BETWEEN @FromDate AND @ToDate
GROUP BY t.MyCol
, t.MyDate;
This is a good starting point, but given your provided variables, you'll only get data from 2016-09-01
to 2017-04-01
rather than 2016-09-01
to 2017-03-31
.
So you'll need to add an additional month. You can do this a variety of ways (Add one to the month and check to see if it's over 13, DATEADD
, etc.)
I chose DATEADD
because it's a little simpler.
Your end result comes up like this:
DECLARE @ToDate AS DATE = DATEADD(MONTH, 1, CONVERT(DATE, CONVERT(VARCHAR, @toYear) + '-' + CONVERT(VARCHAR, @toMonth) + '-1'));
DECLARE @FromDate AS DATE = CONVERT(DATE, CONVERT(VARCHAR, @fromYear) + '-' + CONVERT(VARCHAR, @fromMonth) + '-1');
SELECT t.MyCol
, t.MyDate
FROM #Temp AS t
WHERE t.MyDate >= @FromDate AND
t.MyDate < @ToDate
GROUP BY t.MyCol
, t.MyDate;
Edit: There's probably a cleaner way to generate a date than doing concatenation and converting.
Upvotes: 0