Как группировать по вычисленному полю

Мне нужно сгруппировать по вычисленному полю SQL Server 2005/2008.

У меня есть следующий sql:

select dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue))),
sum(mwspp.QtyRequired)
from manufacturingweekshortagepartpurchasing mwspp
where mwspp.buildScheduleSimID = 10109 and mwspp.partID = 8366
group by mwspp.DateDue
order by mwspp.DateDue

Вместо group by mwspp.DateDue мне нужно сгруппировать по результату вычисления. Возможно ли это?

Заранее спасибо

Ответ 1

Конечно, просто добавьте те же вычисления в предложение GROUP BY:

select dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue))),
sum(mwspp.QtyRequired)
from manufacturingweekshortagepartpurchasing mwspp
where mwspp.buildScheduleSimID = 10109 and mwspp.partID = 8366
group by dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue)))
order by dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue)))

Изменить после комментария:

Как и все вопросы относительно оптимизатора, ответ действительно "зависит", но, скорее всего, он будет выполняться только один раз - вы увидите это в плане выполнения как оператор Вычислить скаляр.

На основе этой вычисления Scalar оптимизатор затем решит, как выполнить фактическую агрегацию.

Другие ответы здесь (CTE/subquery и т.д.) являются одинаково действительными, но на самом деле не изменяют логику - в конечном итоге они будут выполнять аналогичные операции. SQL Server может относиться к ним иначе, но это маловероятно. Однако они помогут с удобочитаемостью.

Если вы беспокоитесь об эффективности, вы можете посмотреть несколько вариантов, например. настраивая вычисление как сохраняемый вычисленный столбец и используя это в индексе или добавляя промежуточные результаты во временную таблицу.

Единственный способ узнать наверняка - проверить статистику выполнения /IO при выполнении запроса в типичном наборе данных и посмотреть, удовлетворены ли вы производительностью; если нет, возможно, исследуя один из вышеуказанных вариантов.

Ответ 2

Если вы хотите GROUP BY вычислять dateadd, тогда вам нужно будет поместить эту формулу в предложение GROUP BY или вы можете обернуть свой запрос в другой SELECT:

select DateCalc,
  sum(QtyRequired) TotalQty
from
(
  select mwspp.DateDue,
    dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue))) DateCalc,
    mwspp.QtyRequired
  from manufacturingweekshortagepartpurchasing mwspp
  where mwspp.buildScheduleSimID = 10109 
    and mwspp.partID = 8366
) src
group by DateCalc
order by DateCalc

Ответ 3

Есть несколько способов сделать это: один включает использование CTE:

with cte as 
(select m.*, 
        dateadd(day, -7, Convert(DateTime, DateDue) + (7 - datepart(weekday, DateDue))) datecalc
 from manufacturingweekshortagepartpurchasing m)
select datecalc, sum(QtyRequired)
from cte
where buildScheduleSimID = 10109 and partID = 8366
group by datecalc
order by datecalc

Ответ 4

Просто разместите расчет в предложении GROUP BY:

Заменить

group by mwspp.DateDue

Для

group by dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue)))