SQL创建一个函数以根据列名获取总和

时间:2017-02-16 17:18:40

标签: sql sql-server tsql

我试着写一个简单的函数,它允许我根据列的值得到总和。

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进行内容描述。

如果我这样做:

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。

任何人都可以解释为什么会这样吗?

2 个答案:

答案 0 :(得分:2)

当您使用GROUP BY子句时,每列都需要在GROUP BY中,或者需要聚合。

在您的第二个示例中,您通过在函数调用周围放置SUM来满足这些要求。在您的第一个示例中,由于函数调用本身并未包含在聚合(SUMMAXMIN等)中,因此您必须将其放在GROUP BY中子句,以便不触发错误。

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

我同意戈登的意见,你可能想重新考虑一下这个策略。

答案 1 :(得分: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
. . .

此查询不需要聚合。