我在View
上设计一个Microsoft SQL Server 2008
,它应该基于很多业务逻辑构建,这意味着有很多CASE WHEN THEN ELSE
语句。问题是,查询中的其他位置经常需要一个CASE
语句的结果,例如函数,联接和其他情况。这使得代码非常臃肿,难以阅读并且难以维护。
以下是此类视图的示例(字段和函数仅用于说明):
SELECT
-- Random complicated case
CASE
WHEN A=B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A
WHEN A<>B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 5
WHEN A=B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 10
WHEN A<>B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 15
END AS ComplicatedCase
-- Use of that same complicated case in another case
CASE
WHEN CASE
WHEN A=B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A
WHEN A<>B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 5
WHEN A=B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 10
WHEN A<>B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 15
END > 300
THEN CASE
WHEN A=B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A
WHEN A<>B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 5
WHEN A=B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 10
WHEN A<>B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 15
END
ELSE NULL
END AS AnotherCase
FROM SomeTable AS T
-- Complicated case in join
INNER JOIN AnotherTable AS AT
ON AT.ID = CASE
WHEN A=B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A
WHEN A<>B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 5
WHEN A=B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 10
WHEN A<>B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 15
END
代码很长,不可读,如果需要更改业务逻辑,我更可能忘记更改。
我遇到的一个明显的解决方案就是将子案例放在子选择中,或者由INNER JOIN
或CROSS APPLY
加入,如下所示:
-- Solution by CROSS APPLY sub-select
SELECT
T1.ComplicatedCase,
CASE
WHEN ComplicatedCase > 300
THEN ComplicatedCase
ELSE NULL
END AS AnotherCase
FROM SomeTable AS T
CROSS APPLY
(
SELECT
CASE
WHEN A=B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A
WHEN A<>B AND CAST(C AS int)=D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 5
WHEN A=B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 10
WHEN A<>B AND CAST(C AS int)<>D AND DATEDIFF(DAY,E,F) > 5
THEN D-A - 15
END AS ComplicatedCase
FROM SomeTable AS ST
WHERE T.ID = ST.ID
) AS T1
INNER JOIN AnotherTable AS AT ON AT.ID = T1.ID
...并且工作正常,但我不知道查询性能是否会受到大规模影响(因为我不太了解引擎如何在内部处理这些内容)。
您是否有关于如何处理此类复杂语句的最佳实践?如果它是一个简单的连接子选择,它对SQL引擎是否重要?
PS:我的案例陈述通常由几个函数组成,主要是datetime
处理和转换。
答案 0 :(得分:2)
我不认为你必须var btns='';
var category = ["fur_", "fts_", "fas_"];
for(i = 1; i < category.length; i++){
btns +='<button type="button" class='+category[i]+' id= "myBtn'+i+'">Button</button>';
}
document.getElementById('div').innerHTML = btns;
var button = document.getElementById('myBtn1');
button.addEventListener('click', function () {
alert('Clicked');
}, false);
CROSS APPLY
两次。
这应该有效:
SomeTable
SELECT T1.ComplicatedCase
, CASE
WHEN ComplicatedCase > 300 THEN ComplicatedCase
ELSE NULL
END AS AnotherCase
FROM SomeTable AS T
CROSS APPLY (
SELECT DATEDIFF(DAY, T.E, T.F)
) AS TT(DayDiff)
CROSS APPLY (
SELECT CASE
WHEN T.A = T.B AND CAST(T.C AS INT) = T.D AND TT.DayDiff > 5 THEN D - A
WHEN T.A <> T.B AND CAST(T.C AS INT) = T.D AND TT.DayDiff > 5 THEN D - A - 5
WHEN T.A = T.B AND CAST(T.C AS INT) <> T.D AND TT.DayDiff > 5 THEN D - A - 10
WHEN T.A <> T.B AND CAST(T.C AS INT) <> T.D AND TT.DayDiff > 5 THEN D - A - 15
END
) AS T1(ComplicatedCase)
INNER JOIN AnotherTable AS AT
ON AT.ID = T1.ComplicatedCase;
允许您创建计算值并在CROSS APPLY
,JOINS
语句中使用它们,等等。它使代码更具可读性,并且不应为您节省额外资源。
如果某些内容不清楚或不符合您的标准,请与我们联系。