Using a DatePart inside a switch case statement
-
18-06-2021 - |
Domanda
I'm a beginner to SQL making a stored procedure with the goal of taking a specified time range and interval, and returning data within that time range grouped by the interval. For example, an input of a two week time range and 2 day interval will give 7 data points of performance.
In order to make the groupings I'm using a switch case for the interval unit and datepart to extract it for grouping. However, my procedure won't compile. Here is my code:
declare @interval int
declare @unit varchar(6)
set @interval=1
set @unit='year'
select
case @unit
when 'year' then datepart(year, CreateDate)/@interval*@interval
when 'month' then datepart(month, CreateDate)/@interval*@interval
when 'week' then datepart(week, CreateDate)/@interval*@interval
when 'day' then datepart(day, CreateDate)/@interval*@interval
when 'hour' then datepart(hour, CreateDate)/@interval*@interval
when 'minute' then datepart(minute, CreateDate)/@interval*@interval
when 'second' then datepart(second, CreateDate)/@interval*@interval
end
from OrderInfoCustom
group by
case @unit
when 'year' then datepart(year, CreateDate)/@interval
when 'month' then datepart(month, CreateDate)/@interval
when 'week' then datepart(week, CreateDate)/@interval
when 'day' then datepart(day, CreateDate)/@interval
when 'hour' then datepart(hour, CreateDate)/@interval
when 'minute' then datepart(minute, CreateDate)/@interval
when 'second' then datepart(second, CreateDate)/@interval
end
This refuses to compile, giving this error (multiple times):
Msg 8120, Level 16, State 1, Line 7 Column 'OrderInfoCustom.CreateDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
It seems the compiler does not recognize that CreateDate is part of the aggregate function, since it is within a switch-case? I'm not sure.
EDIT: I should include I am on Microsoft SQL Server 2005.
Soluzione
Yes, you are grouping by an expression, so you can't use part of that expression in the selection.
If you use the exact same expression, it should work:
select
case @unit
when 'year' then datepart(year, CreateDate)/@interval
when 'month' then datepart(month, CreateDate)/@interval
when 'week' then datepart(week, CreateDate)/@interval
when 'day' then datepart(day, CreateDate)/@interval
when 'hour' then datepart(hour, CreateDate)/@interval
when 'minute' then datepart(minute, CreateDate)/@interval
when 'second' then datepart(second, CreateDate)/@interval
end * @interval
from OrderInfoCustom
group by
case @unit
when 'year' then datepart(year, CreateDate)/@interval
when 'month' then datepart(month, CreateDate)/@interval
when 'week' then datepart(week, CreateDate)/@interval
when 'day' then datepart(day, CreateDate)/@interval
when 'hour' then datepart(hour, CreateDate)/@interval
when 'minute' then datepart(minute, CreateDate)/@interval
when 'second' then datepart(second, CreateDate)/@interval
end
You can also use a subquery:
select y * @interval
from (
select
case @unit
when 'year' then datepart(year, CreateDate)/@interval
when 'month' then datepart(month, CreateDate)/@interval
when 'week' then datepart(week, CreateDate)/@interval
when 'day' then datepart(day, CreateDate)/@interval
when 'hour' then datepart(hour, CreateDate)/@interval
when 'minute' then datepart(minute, CreateDate)/@interval
when 'second' then datepart(second, CreateDate)/@interval
end as y
from OrderInfoCustom
) x
group by y