DRY T-SQL案例陈述

时间:2015-04-27 16:58:29

标签: sql-server tsql sql-server-2012

是否有DRYer方式来编写此案例陈述?

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

这种语法不起作用:

case try_convert(int, [MIXED USE FIELD])
  when between 0 and 5 then 1
  when between 6 and 10 then 2
  when between 11 and 20 then 3
  when > 20 then 4
  else -9
end

**编辑**

示例数据:

0 to 2
> 10
6

由于TRY_CONVERT仅适用于离散值,因此我不确定子查询是否有用。目前,我在不同的代码子分支中处理范围值。

4 个答案:

答案 0 :(得分:3)

您可以执行获取try_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
-- use BETWEEN
SELECT  CASE 
        WHEN s.converted BETWEEN 0 AND 5 THEN 1
        WHEN s.converted BETWEEN 6 AND 9 THEN 2
        WHEN s.converted BETWEEN 11 AND 20 THEN 3
        WHEN s.converted > 20 THEN 0 
        END calc
FROM    (
            SELECT converted = try_convert([MIXED_USE_FIELD])
            FROM TABLE
        ) s

答案 1 :(得分:2)

你可以这样做:

object(stdClass)[4]
public 'lib' => 
    object(stdClass)[3]
        public 'test' => 
          object(stdClass)[2]
            public 'test2' => 
              object(stdClass)[1]
                ...
object(stdClass)[3]
public 'test' => 
    object(stdClass)[2]
        public 'test2' => 
        object(stdClass)[1]

array (size=2)
0 => string 'test' (length=4)
1 => string 'test2' (length=5)

object(stdClass)[4]
public 'lib' => 
    object(stdClass)[3]
        public 'test' => &
        object(stdClass)[2]

Notice: Undefined property: stdClass::$test2

答案 2 :(得分:1)

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

SQL不是一种漂亮的语言。不要试着把口红涂在猪身上。

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)

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

答案 3 :(得分:0)

我使用CROSS APPLY进行转换,并使用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