我可以使用SQL函数执行此操作

时间:2016-04-01 13:36:23

标签: sql-server sql-server-2012

关于MS SQL2012中函数的一般性问题。我已经使用SQL 15年了,并且已经将大部分内容用于相当高级的水平,但从未使用过函数。

我只是想知道一个功能是否可以用于以下......

我的查询有一个大的case语句,查询也按case语句的结果分组 - 这意味着我对case语句所做的每一个更改都必须在Group By子句中复制,这个维护是非常耗时的(特别是因为我总是忘记更新group by子句中的case语句)。

这是我查询的理论示例....

Select
Field1,
Field2,
Field3,
Field4,
Case
when Field2 like ('%abc%') then 'Category1'
when Field2 like ('%def%') then 'Category2'
/*plus around 20 more 'when' lines*/
else 'CategoryX' end as 'Category'

From table 
Group by
Case
when Field2 like ('%abc%') then 'Category1'
when Field2 like ('%def%') then 'Category2'
/*plus around 20 more 'when' lines*/
else 'CategoryX' end

我知道我可以对它进行子查询,然后通过subQuery.Category进行分组,但是,由于我之前从未使用过函数,我只是想知道我是否可以创建Category接受Field2的函数,运行case语句并将结果与​​表中的其余数据一起输出?

3 个答案:

答案 0 :(得分:3)

比用户定义的函数(在我看来)更好的是计算列:

alter table
    add category as (Case when Field2 like ('%abc%') then 'Category1'
                          when Field2 like ('%def%') then 'Category2'
                          /*plus around 20 more 'when' lines*/
                          else 'CategoryX'
                     end);

为什么我比功能更喜欢这个?

  • 它将定义与特定表和field2列绑定。
  • 调用用户定义的函数有一些开销,因此计算列更快。
  • 您有机会在category上创建索引。
  • 该表格的所有用户都会看到category列,并且会正确填充。

修改列需要删除并重新添加。

一个缺点是用户需要正确的权限才能添加列。删除并重新添加列可能会对使用SCHEMABINDING的代码产生影响。 (为什么SQL Server不允许修改计算列?)

请注意,此解决方案和函数都有一个缺点:逻辑在查询中不明显,因此在不同时间运行的相同查询可能会产生不同的结果。

答案 1 :(得分:2)

您可以创建内联表函数来隐藏复杂的逻辑:

    create function dbo.udfGetR 
    (
     --param here
    )
    returns table 
    as return 

   Select
          Field1,
          Field2,
          Field3,
          Field4,
          Case
                when Field2 like ('%abc%') then 'Category1'
                when Field2 like ('%def%') then 'Category2'
                /*plus around 20 more 'when' lines*/
                else 'CategoryX' end as 'Category'

          From table 
          Group by
          Case
          when Field2 like ('%abc%') then 'Category1'
          when Field2 like ('%def%') then 'Category2'
          /*plus around 20 more 'when' lines*/
          else 'CategoryX' end

称之为

         select * from dbo.udfGetR(--param)

答案 2 :(得分:1)

另外两个明显的解决方案:

使用CTE:

WITH cte As
(
    SELECT
        ...
        CASE
            WHEN Field2 like '%abc%' THEN 'Category1'
            ...
            ELSE 'CategoryX' 
        END As 'Category'
    FROM 
        table 
)
SELECT
    ...
FROM
    cte
GROUP BY
    Category
;

使用CROSS APPLY

SELECT
    ...
    C.Category
FROM 
    table As T
    CROSS APPLY
    (
        SELECT 
            CASE
                WHEN T.Field2 Like '%abc%' THEN 'Category1'
                ...
                ELSE 'CategoryX'
            END
    ) As C (Category)
GROUP BY
    C.Category
;