вызов пользовательской функции из представления

#sql #sql-server #tsql

#sql #sql-сервер #tsql

Вопрос:

У меня есть 4 отдельные пользовательские функции, которые мне нужно вызвать на основе значения другого столбца (состояния). Я могу заставить ее работать, когда я размещаю пользовательскую функцию после ВЫБОРА, однако мне нужно, чтобы она была размещена после того, как.

Вот код:

   SELECT Fname, Lname, id, State, TotalWedThurMins, StCode
    FROM dbo.AnnualRegCredits
GROUP BY Fname, Lname, id, State, TotalWedThurMins, StCode
  HAVING (State = 'HI') 
     AND (dbo.roundnearestquarter(SUM(TotalWedThurMins)) > 0) 
  

Есть предложения?

Комментарии:

1. Можете ли вы объяснить проблему более подробно?

2. Я думаю, вам следует изменить HAVING (State = 'HI') на WHERE (State = 'HI') .

3. да, каждое состояние должно округляться по-разному. ‘HI’ должно быть округлено до ближайшей четверти (.25). Время должно быть округлено до ближайшего получаса (.5). У меня есть все функции, созданные и работающие, но я застрял, пытаясь заставить их соответствовать каждому состоянию на мой взгляд. Имеет смысл?

Ответ №1:

Конечно

НАЛИЧИЕ предназначено для фильтрации после агрегирования (например, после ГРУППИРОВАНИЯ ПО). SUM(TotalWedThurMins) является агрегированным. Таким образом, udf, использующий SUM в качестве анализатора, переходит в HAVING not WHERE .

SUM(TotalWedThurMins) не определено и не имеет смысла в предложении WHERE

Однако, State не агрегируется и может быть в предложении WHERE .

Итак, это выглядит следующим образом. Но зачем ГРУППИРОВАТЬ ПО, а затем суммировать TotalWedThurMins ? Возможно, вам нужно предложение OVER для управления обоими … (не уверен, что это допустимый синтаксис)

 SELECT Fname, Lname, id, State, TotalWedThurMins, StCode
FROM dbo.AnnualRegCredits
WHERE (State = 'HI') 
GROUP BY Fname, Lname, id, State, TotalWedThurMins, StCode
HAVING (dbo.roundnearestquarter(SUM(TotalWedThurMins) OVER ()) > 0) 
  

Альтернативная формулировка с использованием OVER и CTE:

 WITH CTE AS
(
    SELECT Fname, Lname, id, State, TotalWedThurMins, StCode,
           SUM(TotalWedThurMins) OVER () AS SumTotalWedThurMins
    FROM dbo.AnnualRegCredits
    WHERE State = 'HI'
)
SELECT 
     Fname, Lname, id, State, TotalWedThurMins, StCode
FROM
    CTE
WHERE
    dbo.roundnearestquarter(SumTotalWedThurMins) > 0
  

Комментарии:

1. Спасибо, это сработает, но мне нужно что-то другое. Я разместил неверный код. Приведенный ниже код работает для двух состояний (HI и FL). Однако мне нужна другая функция для MD. Как мне вызвать другую функцию в том же представлении: ВЫБЕРИТЕ Fname, Lname, id, State, dbo.GetRoundDownNearestQuarter(TotalWedThurMins) КАК Expr1, StCode ИЗ dbo. Ежегодные учетные записи, ГДЕ (State = ‘HI’) ИЛИ (State = ‘FL’) ГРУППИРУЮТСЯ По Fname, Lname, id, State, TotalWedThurMins, StCode

2. Отличное объединение, все сработало! Спасибо! Как обычно, простые вещи никогда не приходят на ум первыми!

Ответ №2:

Вы также можете использовать оператор APPLY, вот ссылка на хорошую статью, объясняющую использование и опции. Оператор APPLY позволяет присоединять таблицы к определенным типам функций.