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.

È stato utile?

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top