Sql server DRY T-SQL case语句

Sql server DRY T-SQL case语句,sql-server,tsql,sql-server-2012,Sql Server,Tsql,Sql Server 2012,有没有更干练的方法来写这个案例陈述 case when try_convert(int, [MIXED USE FIELD]) >= 0 and try_convert(int, [MIXED USE FIELD]) <= 5 then 1 ... when try_convert(int, [MIXED USE FIELD]) > 20 then 2 else -9 end **编辑** 样本数据: 0 to 2 > 10 6 由于TRY\u CO

有没有更干练的方法来写这个案例陈述

case 
  when try_convert(int, [MIXED USE FIELD]) >= 0 and try_convert(int, [MIXED USE FIELD]) <= 5 then 1
  ...
  when try_convert(int, [MIXED USE FIELD]) > 20 then 2
  else -9
end
**编辑**

样本数据:

0 to 2
> 10
6

由于
TRY\u CONVERT
只能处理离散值,因此我不确定子查询是否有用。目前,我正在处理不同代码子分支中的范围值。

您可以执行一个子查询以获取try\u convert结果,然后外部查询运行case语句。大概是这样的:

-- use equivalence
SELECT  CASE 
        WHEN s.converted >= 0 AND s.converted < 6 THEN 1
        WHEN s.converted >= 6 AND s.converted < 11 THEN 2
        WHEN s.converted >= 11 AND s.converted < THEN 3
        WHEN s.converted > 20 THEN 4
        END calc
FROM    (
            SELECT converted = try_convert([MIXED_USE_FIELD])
            FROM TABLE
        ) s
...
    case
        when tc.c between 0 and 5 then 1
        when tc.c between 6 and 10 then 2
        when tc.c between 11 and 20 then 3
        when tc.c > 20 then 4
        else -9
    end
from ... as a
    outer apply (select ry_convert(int, [MIXED USE FIELD]) as tc) as c

你可以这样做:

-- use equivalence
SELECT  CASE 
        WHEN s.converted >= 0 AND s.converted < 6 THEN 1
        WHEN s.converted >= 6 AND s.converted < 11 THEN 2
        WHEN s.converted >= 11 AND s.converted < THEN 3
        WHEN s.converted > 20 THEN 4
        END calc
FROM    (
            SELECT converted = try_convert([MIXED_USE_FIELD])
            FROM TABLE
        ) s
...
    case
        when tc.c between 0 and 5 then 1
        when tc.c between 6 and 10 then 2
        when tc.c between 11 and 20 then 3
        when tc.c > 20 then 4
        else -9
    end
from ... as a
    outer apply (select ry_convert(int, [MIXED USE FIELD]) as tc) as c

我使用crossapply进行转换,并对case语句使用一些算法。试一试:

DECLARE @Table TABLE ([MIXED USE FIELD] VARCHAR(2));
INSERT INTO @Table 
VALUES  ('1'),('6'),('15'),('21'),('-1');

SELECT  [MIXED USE FIELD],
        CASE
            WHEN MUF_int BETWEEN 0 AND 20 THEN CEILING(muf_int/5.0)
            WHEN MUF_int > 20 THEN 4
            ELSE -9
        END case_results
FROM @Table
CROSS APPLY (SELECT TRY_CONVERT(INT,[MIXED USE FIELD])) AS CA(MUF_int)
结果:

MIXED USE FIELD case_results
--------------- ---------------------------------------
1               1
6               2
15              3
21              4
-1              -9

在这种情况下,我不会尝试重构。如果您的目标是可读、可维护的代码,那么用一个足够描述性的名称来代替
try\u convert()
将与函数本身一样冗长。没有足够的额外清晰度来证明额外的间接性

SQL不是一种漂亮的语言。不要把口红贴在猪身上。< / P>
select
  case 
    when try_convert(int, [MIXED USE FIELD]) between  0 and  5 then 1
    when try_convert(int, [MIXED USE FIELD]) between  6 and 10 then 2
    when try_convert(int, [MIXED USE FIELD]) between 11 and 20 then 3
    when try_convert(int, [MIXED USE FIELD]) > 20              then 4
    else -9
  end
from MyTable t1
与:

select
  case 
    when [MIXED USE FIELD as int] between  0 and  5 then 1
    when [MIXED USE FIELD as int] between  6 and 10 then 2
    when [MIXED USE FIELD as int] between 11 and 20 then 3
    when [MIXED USE FIELD as int] > 20              then 4
    else -9
  end
from MyTable t1
cross apply (
  select try_convert(int, [MIXED USE FIELD]) as [MIXED USE FIELD as int]
) t2

另一种方法是用SQL方式重写:将业务规则封装在数据中,而不是代码中。将这些范围移动到表中

CREATE TABLE MyRangeFilterTable (
  [RangeFrom] int DEFAULT -2147483648
 ,[RangeTo]   int DEFAULT  2147483647
 ,[Value]     int
)

INSERT MyRangeFilterTable VALUES
  ( 0,   5, 1)
 ,( 6,  10, 2)
 ,(11,  20, 3)
 ,(20, DEFAULT, 4)
 ,(NULL, NULL, -9)

SELECT
  [Value]
FROM MyTable
INNER JOIN MyRangeFilterTable
  ON (TRY_CONVERT(int, [MIXED USE FIELD]) BETWEEN [RangeFrom] AND [RangeTo])
  OR (TRY_CONVERT(int, [MIXED USE FIELD]) IS NULL AND [RangeFrom] IS NULL)

现在,您可以在不更改代码的情况下更改规则。

您可以使用CTE或派生表来避免try\u转换的重复,但这就是我所能想到的您所能做的。您的唯一问题是,如果记录太多,则加入try\u转换可能会非常慢。我喜欢MyRangeFilterIdea,但是做子查询(或定义函数)可能比连接更好。