2017-02-16 12 views
1

Я пытаюсь написать простую функцию, которая позволит мне получить сумму, основанную на значении столбца.SQL Создание функции для получения суммы на основе имени столбца

CREATE FUNCTION [GetSumOfColumnByCase](@column varchar(50), @case int) 
    RETURNS INT 
AS 
BEGIN 

    declare @return int 
    set @return = SUM(CASE WHEN @column = @case THEN 1 ELSE 0 END) 

    -- Return the result of the function 
    return @return 

END 
GO 

Я называю эту функцию так:

 SELECT HouseDescription, 
       [dbo].[GetSumOfColumnByCase]([HouseTypeId], 1) AS "houseType1", 
       [dbo].[GetSumOfColumnByCase]([HouseTypeId], 2) AS "houseType2" 

Поступать таким образом заставляет меня GROUP BY как houseDescription и HouseTypeId столбцов, но я просто хочу, чтобы GROUP BY в housedescription.

Если я делать вещи так:

SELECT HouseDescription, 
     SUM(CASE WHEN HouseTypeId = 1 THEN 1 ELSE 0 END) AS "houseType1", 
     SUM(CASE WHEN HouseTypeId = 2 THEN 1 ELSE 0 END) AS "houseType2" 

Его штраф, он не заставит меня GROUP BY HouseTypeId.

Может ли кто-нибудь объяснить, почему это так?

+0

В основном вы не можете это сделать в SQL Server. Для обработки столбца переменной вам нужен динамический SQL. Функция не может легко запускать динамический SQL. –

ответ

2

Когда вы используете предложение GROUP BY, каждый столбец должен либо находиться в GROUP BY, либо его необходимо агрегировать.

В вашем втором примере вы выполняете эти требования - разместив SUM вокруг вызова функции. В первом примере, поскольку сам вызов функции не завернут в агрегацию (SUM, MAX, MIN и т. Д.), Вы должны поместить его в предложение GROUP BY, чтобы не вызвать ошибку.

https://msdn.microsoft.com/en-us/library/ms177673.aspx

Я согласен с Гордоном, хотя, вы можете пересмотреть свою стратегию для этого.

+0

Это ответ. SUM находится в функции, а не в основном запросе. –

+0

@ Джон Thompson, спасибо Джон это имеет большой смысл и место на Ive переработал мою функцию, чтобы использовать только оператор case и поместил агрегат перед вызовом функции. Прекрасно работает. –

0

Вы не можете делать то, что хотите, с помощью функции, поскольку SQL Server не поддерживает динамический SQL (легко) в функциях. А для обработки любой столбец вам понадобится динамический SQL.

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

SELECT SUM(CASE WHEN HouseTypeId = 1 THEN 1 ELSE 0 END) OVER() AS houseType1, 
     SUM(CASE WHEN HouseTypeId = 2 THEN 1 ELSE 0 END) OVER() AS houseType2 
. . . 

агрегирование не требуется для этого запроса.

+0

Посмотрите внимательно на функцию. Я не думаю, что это ответ. Он не пытается делать динамический sql в функции. Он передает значение, а не имя столбца. Использование '@ column' в качестве имени параметра обманчиво. –

+0

@ Gordon Linoff Спасибо, Гордон, это интересная тема. Ответ Джонса помог мне переработать мою функцию, так что мне не нужно группировать HouseTypeId. –

+0

@TabAlleman. , , Код говорит '@column = @ case', и в этом примере, похоже, хочет делать то, что делает функция Windows. –