T-SQL将If-Else(Case-When)替换为查找表
*编辑 正如我所指出的,我的问题提供了必要的细节。所以我会尽量精确 crystal报表中使用了膨胀的If-Else结构。结果是csv导出。这就是它现在的工作方式设计决策是重新设计并生成动态SQL。因此,这些臃肿的If-Else结构将成为SQL查询的一部分 现在我已经实现了一个modell,以便能够动态创建T-SQL。我提出了一个表,其中包含查询的Select部分的列定义,一个表包含连接条件,一个表包含where条件。在存储过程中,收集所有信息,并生成T-SQl查询 选择列定义表:T-SQL将If-Else(Case-When)替换为查找表,sql,if-statement,sql-server-2012,lookup,case-when,Sql,If Statement,Sql Server 2012,Lookup,Case When,*编辑 正如我所指出的,我的问题提供了必要的细节。所以我会尽量精确 crystal报表中使用了膨胀的If-Else结构。结果是csv导出。这就是它现在的工作方式设计决策是重新设计并生成动态SQL。因此,这些臃肿的If-Else结构将成为SQL查询的一部分 现在我已经实现了一个modell,以便能够动态创建T-SQL。我提出了一个表,其中包含查询的Select部分的列定义,一个表包含连接条件,一个表包含where条件。在存储过程中,收集所有信息,并生成T-SQl查询 选择列定义表: ColumnN
ColumnName T-SQL OrderID IncludeInSelectList InterfaceID_ID
Monat SUBSTRING(CP.TCOEP_PERIO, 2,2) 1 1 1
Jahr CP.TCOEP_GJAHR 2 1 1
问题在于,在具有列定义的表中,存储SQL定义的列(例如SubstringColA,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'
。。。。等等
我知道我可以把它改写成一个案例。问题是,这需要存储在最大长度为NVARCH4000的表中。我尝试用如下所示的查找表来解决此问题:
lookupColumnName | lookupValue | lookupResultName | lookupResult
我试图用一种更通用的方式编写查询,如:
这是我第一次尝试实现origanel If-Else结构的顺序:
但这种方法也可能导致一个包含4000多个字符的字符串
现在我被卡住了。有更好的方法吗?您尝试使用更通用的方法,这促使我想到:
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 dbo.GetLookUp('ColA')
FROM
SourceTable
这意味着你可以保存很多字符
但我必须承认,整个概念对我来说并不清楚,而且相当复杂。也许您想提供有关表结构、一些示例数据和预期输出的详细信息
我很确定,有更好的方法…很难遵循您的确切逻辑,因为它非常复杂,而且没有列具有表别名,所以我不知道哪个列属于哪个表 不过,我已经试一试。由于要多次重用同一个相关子查询,因此将这些子查询移动到应用程序可能会有好处,这样结果就可以重用。然后我试着把你的逻辑分开,替换如下语句:
CASE WHEN <expression1> IS NULL THEN <expression2> ELSE <expression1> END
与
给出以下内容的最终查询:
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;
还没有想过使用交叉应用。谢谢,我喜欢这种方法。也许OP想把你和我的建议与UDF结合起来,这样做会更容易+1从我的角度来看,这真的是一种保存字符的方法。我担心,你的编辑并没有让事情变得更好;-使用实际表的结构、一些示例数据和您尝试过的内容建立一个SQLFIDDLESQLFIDLE.com会有所帮助。然后发布预期的输出。很抱歉响应太晚。我把你的建议和GarethD的建议结合起来了。我对结果很满意。非常感谢。很高兴看到你能解决这个问题!
SELECT dbo.GetLookUp('ColA')
FROM
SourceTable
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;