T-SQL 用查找替换 If Else (Case When) table
T-SQL Replacing If Else (Case When) with lookup table
*编辑
正如我所指出的,我的问题提供了必要的细节。所以我会尽量准确。
crystal 报告中使用了臃肿的 If Else 结构。结果是一个 csv 导出。这就是它现在的工作方式。 :) 设计决策是对此进行返工并生成动态 SQL。这样这些臃肿的 If Else 结构将成为 SQL 查询的一部分。
现在我已经实现了一个能够动态创建 T-SQL 的模型。我想出了一个 table 来保存查询的 Select 部分的列定义,一个 table 保存连接条件,一个 table 保存哪里的条件。在存储过程中收集所有信息,结果是 T-SQl 查询。
SELECT 列定义 Table:
ColumnName T-SQL OrderID IncludeInSelectList InterfaceID_ID
Monat SUBSTRING(CP.TCOEP_PERIO, 2,2) 1 1 1
Jahr CP.TCOEP_GJAHR 2 1 1
问题是在带有列定义的 table 中,将存储 SQL 定义的列(例如 Substring(ColA, 2,3))的最大长度限制为 4000字符。
我越是试图解释它,我就越觉得试图将所有内容都放入一个巨大的查询中根本不是一个好主意。我想我必须和我的上司谈谈。 ;)
*编辑
我在替换臃肿的 If Else 结构时遇到问题。这是一个例子:
If ColA startswith 'ABC' then 'Ext' else
If ColB startswith 'DBC' then 'Int' else
If ColC startswith ('CCC', 'DDD','EEE', ..) then 'N/A'
.....等等。
我知道我可以将其重写为 Case When 结构。问题是这需要存储在最大长度为 nvarchar(4000) 的 table 中。我试图通过查找 table 来解决这个问题,如下所示:
lookupColumnName |查找值 |查找结果名称 |查找结果
我试图以更 "generic" 的方式编写查询,例如:
SELECT
(SELECT lookupResult from lookupTable where lookupColumn = 'ColA')
FROM
SourceTable
这是我第一次尝试实现organel If Else结构的顺序:
CASE WHEN
CASE WHEN
CASE WHEN
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) IS NULL THEN (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'XBLNR' AND BKPF_XBLNR like lookupValue order by len(lookupValue) DESC
) ELSE (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) END
<> 'LEER' THEN
CASE WHEN
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) IS NULL THEN (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'XBLNR' AND BKPF_XBLNR like lookupValue order by len(lookupValue) DESC
) ELSE (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) END
ELSE
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'SGTXT' AND COEP_SGTXT like lookupValue order by len(lookupValue) DESC
)
END IS NULL THEN 'App'
ELSE
CASE WHEN
CASE WHEN
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) IS NULL THEN (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'XBLNR' AND BKPF_XBLNR like lookupValue order by len(lookupValue) DESC
) ELSE (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) END
<> 'LEER' THEN
CASE WHEN
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) IS NULL THEN (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'XBLNR' AND BKPF_XBLNR like lookupValue order by len(lookupValue) DESC
) ELSE (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) END
ELSE
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'SGTXT' AND COEP_SGTXT like lookupValue order by len(lookupValue) DESC
)
END
END
但这种方法也可能导致包含超过 4000 个字符的字符串。
现在我卡住了。有没有更好的方法?
你尝试使用 "more generic" 方式,促使我产生了这个想法:
CREATE FUNCTION dbo.GetLookUp(@LookupColumnName AS VARCHAR(100))
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE @RetVal VARCHAR(100)='#missing value!!!';
SELECT lookupResult from lookupTable where lookupColumn = @LookupColumnName;
RETURN @RetVal;
END
你的
SELECT
(SELECT lookupResult from lookupTable where lookupColumn = 'ColA')
FROM
SourceTable
转入
SELECT dbo.GetLookUp('ColA')
FROM
SourceTable
那意味着你节省了很多字符。
但我必须承认,整个概念对我来说并不清楚,而且有相当多的复杂性。也许您想提供有关 table 结构、一些示例数据和预期输出的详细信息。
我很确定,有一些更好的方法...
很难完全遵循您的逻辑,因为它非常复杂,而且没有任何列具有 table 别名这一事实也无济于事,所以我不知道哪个列属于哪个 table.
不过我试了一下。由于您多次重复使用相同的相关子查询,因此将这些子查询移至 APPLY 以便可以重复使用结果可能会有所帮助。然后我只是试图拆开你的逻辑来替换像这样的语句:
CASE WHEN <expression1> IS NULL THEN <expression2> ELSE <expression1> END
与
ISNULL(<expression1>, <expression2>)
给出最终查询:
SELECT CASE WHEN ISNULL(BKTXT.LookupResult, XBLNR.LookupResult) <> 'LEER' THEN
ISNULL(BKTXT.LookupResult, XBLNR.LookupResult)
ELSE
ISNULL(SGTXT.LookupResult, 'App')
END
FROM SourceTable
CROSS APPLY
( SELECT TOP 1 lookupResult
FROM ##lookupDefinition
WHERE lookupColumnName = 'BKTXT'
AND COEP_SGTXT LIKE lookupValue
ORDER BY LEN(lookupValue) DESC
) AS BKTXT
CROSS APPLY
( SELECT TOP 1 lookupResult
FROM ##lookupDefinition
WHERE lookupColumnName = 'XBLNR'
AND COEP_SGTXT LIKE lookupValue
ORDER BY LEN(lookupValue) DESC
) AS XBLNR
CROSS APPLY
( SELECT TOP 1 lookupResult
FROM ##lookupDefinition
WHERE lookupColumnName = 'SGTXT'
AND COEP_SGTXT LIKE lookupValue
ORDER BY LEN(lookupValue) DESC
) AS SGTXT;
*编辑
正如我所指出的,我的问题提供了必要的细节。所以我会尽量准确。
crystal 报告中使用了臃肿的 If Else 结构。结果是一个 csv 导出。这就是它现在的工作方式。 :) 设计决策是对此进行返工并生成动态 SQL。这样这些臃肿的 If Else 结构将成为 SQL 查询的一部分。
现在我已经实现了一个能够动态创建 T-SQL 的模型。我想出了一个 table 来保存查询的 Select 部分的列定义,一个 table 保存连接条件,一个 table 保存哪里的条件。在存储过程中收集所有信息,结果是 T-SQl 查询。
SELECT 列定义 Table:
ColumnName T-SQL OrderID IncludeInSelectList InterfaceID_ID
Monat SUBSTRING(CP.TCOEP_PERIO, 2,2) 1 1 1
Jahr CP.TCOEP_GJAHR 2 1 1
问题是在带有列定义的 table 中,将存储 SQL 定义的列(例如 Substring(ColA, 2,3))的最大长度限制为 4000字符。
我越是试图解释它,我就越觉得试图将所有内容都放入一个巨大的查询中根本不是一个好主意。我想我必须和我的上司谈谈。 ;) *编辑
我在替换臃肿的 If Else 结构时遇到问题。这是一个例子:
If ColA startswith 'ABC' then 'Ext' else
If ColB startswith 'DBC' then 'Int' else
If ColC startswith ('CCC', 'DDD','EEE', ..) then 'N/A'
.....等等。
我知道我可以将其重写为 Case When 结构。问题是这需要存储在最大长度为 nvarchar(4000) 的 table 中。我试图通过查找 table 来解决这个问题,如下所示:
lookupColumnName |查找值 |查找结果名称 |查找结果
我试图以更 "generic" 的方式编写查询,例如:
SELECT
(SELECT lookupResult from lookupTable where lookupColumn = 'ColA')
FROM
SourceTable
这是我第一次尝试实现organel If Else结构的顺序:
CASE WHEN
CASE WHEN
CASE WHEN
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) IS NULL THEN (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'XBLNR' AND BKPF_XBLNR like lookupValue order by len(lookupValue) DESC
) ELSE (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) END
<> 'LEER' THEN
CASE WHEN
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) IS NULL THEN (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'XBLNR' AND BKPF_XBLNR like lookupValue order by len(lookupValue) DESC
) ELSE (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) END
ELSE
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'SGTXT' AND COEP_SGTXT like lookupValue order by len(lookupValue) DESC
)
END IS NULL THEN 'App'
ELSE
CASE WHEN
CASE WHEN
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) IS NULL THEN (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'XBLNR' AND BKPF_XBLNR like lookupValue order by len(lookupValue) DESC
) ELSE (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) END
<> 'LEER' THEN
CASE WHEN
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) IS NULL THEN (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'XBLNR' AND BKPF_XBLNR like lookupValue order by len(lookupValue) DESC
) ELSE (
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'BKTXT' AND BKPF_BKTXT like lookupValue order by len(lookupValue) DESC
) END
ELSE
(
SELECT TOP 1 lookupResult FROM ##lookupDefinition where lookupColumnName = 'SGTXT' AND COEP_SGTXT like lookupValue order by len(lookupValue) DESC
)
END
END
但这种方法也可能导致包含超过 4000 个字符的字符串。
现在我卡住了。有没有更好的方法?
你尝试使用 "more generic" 方式,促使我产生了这个想法:
CREATE FUNCTION dbo.GetLookUp(@LookupColumnName AS VARCHAR(100))
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE @RetVal VARCHAR(100)='#missing value!!!';
SELECT lookupResult from lookupTable where lookupColumn = @LookupColumnName;
RETURN @RetVal;
END
你的
SELECT
(SELECT lookupResult from lookupTable where lookupColumn = 'ColA')
FROM
SourceTable
转入
SELECT dbo.GetLookUp('ColA')
FROM
SourceTable
那意味着你节省了很多字符。
但我必须承认,整个概念对我来说并不清楚,而且有相当多的复杂性。也许您想提供有关 table 结构、一些示例数据和预期输出的详细信息。
我很确定,有一些更好的方法...
很难完全遵循您的逻辑,因为它非常复杂,而且没有任何列具有 table 别名这一事实也无济于事,所以我不知道哪个列属于哪个 table.
不过我试了一下。由于您多次重复使用相同的相关子查询,因此将这些子查询移至 APPLY 以便可以重复使用结果可能会有所帮助。然后我只是试图拆开你的逻辑来替换像这样的语句:
CASE WHEN <expression1> IS NULL THEN <expression2> ELSE <expression1> END
与
ISNULL(<expression1>, <expression2>)
给出最终查询:
SELECT CASE WHEN ISNULL(BKTXT.LookupResult, XBLNR.LookupResult) <> 'LEER' THEN
ISNULL(BKTXT.LookupResult, XBLNR.LookupResult)
ELSE
ISNULL(SGTXT.LookupResult, 'App')
END
FROM SourceTable
CROSS APPLY
( SELECT TOP 1 lookupResult
FROM ##lookupDefinition
WHERE lookupColumnName = 'BKTXT'
AND COEP_SGTXT LIKE lookupValue
ORDER BY LEN(lookupValue) DESC
) AS BKTXT
CROSS APPLY
( SELECT TOP 1 lookupResult
FROM ##lookupDefinition
WHERE lookupColumnName = 'XBLNR'
AND COEP_SGTXT LIKE lookupValue
ORDER BY LEN(lookupValue) DESC
) AS XBLNR
CROSS APPLY
( SELECT TOP 1 lookupResult
FROM ##lookupDefinition
WHERE lookupColumnName = 'SGTXT'
AND COEP_SGTXT LIKE lookupValue
ORDER BY LEN(lookupValue) DESC
) AS SGTXT;