使用 SQL Server 2008 R2 的动态案例语句

Posted

技术标签:

【中文标题】使用 SQL Server 2008 R2 的动态案例语句【英文标题】:Dynamic case statement using SQL Server 2008 R2 【发布时间】:2014-12-11 17:10:50 【问题描述】:

我有如下case语句如下图:

例子:

我有case statement

case cola 
    when cola between '2001-01-01' and '2001-01-05' then 'G1'
    when cola between '2001-01-10' and '2001-01-15' then 'G2'
    when cola between '2001-01-20' and '2001-01-25' then 'G3'
    when cola between '2001-02-01' and '2001-02-05' then 'G4'
    when cola between '2001-02-10' and '2001-02-15' then 'G5'
    else '' 
end

注意:现在我想创建动态案例语句,因为值日期和名称作为参数传递,它可能会改变。

Declare @dates varchar(max) = '2001-01-01to2001-01-05,2001-01-10to2001-01-15,
                               2001-01-20to2001-01-25,2001-02-01to2001-02-05,
                               2001-02-10to2001-02-15'

Declare @names varchar(max) = 'G1,G2,G3,G4,G5'

变量中的值可能会根据要求而变化,它将是动态的。所以case语句应该是动态的,不使用循环。

我的失败尝试

DECLARE @Name varchar(max)
DECLARE @Dates varchar(max)
DECLARE @SQL varchar(max)
DECLARE @SQL1 varchar(max)

SET @Name = 'G1,G2,G3,G4,G5'
SET @dates = '2001-01-01to2001-01-05,2001-01-10to2001-01-15,
              2001-01-20to2001-01-25,2001-02-01to2001-02-05,
              2001-02-10to2001-02-15'

SELECT @SQL =  STUFF((SELECT  ' ' + Value FROM 
(
SELECT 'WHEN Cola Between '''' AND '''' THEN ''' + A.Value + '''' AS Value 
FROM 
(
    SELECT 
        Split.a.value('.', 'VARCHAR(100)') AS Value  
        FROM  
        (
        SELECT CAST ('<M>' + REPLACE(@Name, ',',
            '</M><M>') + '</M>' AS XML) AS Value 
        ) AS A 
        CROSS APPLY Value.nodes ('/M') AS Split(a)
 ) AS A
) AS B
FOR XML PATH (''), type).value('.', 'Varchar(max)'),1,1,'') + ''

SET @SQL1 = 'CASE Cola '+@SQL+' ELSE '''' END'

PRINT(@SQL1);

卡住:但是卡住了@dates2001-01-01to2001-01-05 进入BETWEEN '2001-01-01' AND '2001-01-05'

【问题讨论】:

您为什么要这样做?好像你在这里把一个简单的问题复杂化了。 只需创建一个包含名称、开始日期和结束日期的查找表。然后你只需要将它加入到你的查询中。如果它们每年都重置,请将列设为 yearnamestart_dateend_date 【参考方案1】:

只需创建一个临时表(可以动态插入)并在LEFT JOIN 中使用它。 LEFT JOIN(连同COALESCE)说明ELSE '' 条件,但如果没有ELSE 条件并且所有范围都在数据中表示,则应使用INNER JOIN(并且不需要COALESCE)。

为了从两个单独的变量动态填充临时表,这些变量的数据仅按 CSV 列表中的位置对齐,其中一个是二维数组,需要在逗号和字符串“to ",我使用了 CTE(以便更容易拆分二维 @Dates 变量)和基于 SQLCLR 的字符串拆分器。我使用的拆分器来自SQL# 库(我是它的创建者,但此功能在免费版本中)但您可以使用任何您喜欢的拆分器(但请不要使用基于 WHILE 循环的拆分器)很傻)。

CREATE TABLE #Cola
(
  StartDate DATETIME NOT NULL,
  EndDate DATETIME NOT NULL,
  Name NVARCHAR(50) NOT NULL
);

DECLARE @Dates VARCHAR(MAX) = '2001-01-01to2001-01-05,2001-01-10to2001-01-15,
                               2001-01-20to2001-01-25,2001-02-01to2001-02-05,
                               2001-02-10to2001-02-15';

DECLARE @Names VARCHAR(MAX) = 'G1,G2,G3,G4,G5';

-- dynamic population of temp table from two variables (@Dates being 2 dimensional)
;WITH cte AS
(
  SELECT vals.SplitNum,
         vals.SplitVal,
         CHARINDEX(N'to', vals.SplitVal) AS [WhereToSplit]
  FROM   SQL#.String_Split4k(@dates, ',', 1) vals
)
INSERT INTO #Cola (StartDate, EndDate, Name)
  SELECT CONVERT(DATETIME, SUBSTRING(cte.SplitVal, (cte.WhereToSplit - 10), 10)),
         CONVERT(DATETIME, SUBSTRING(cte.SplitVal, (cte.WhereToSplit + 2), 10)),
         names.SplitVal
  FROM cte
  INNER JOIN SQL#.String_Split4k(@names, ',', 1) names
          ON names.SplitNum = cte.SplitNum; -- keep the values aligned by position


SELECT tab.fields, COALESCE(cola.[Name], '') AS [Cola]
FROM   SchemaName.TableName tab
LEFT JOIN #Cola cola
        ON tab.cola BETWEEN cola.StartDate AND cola.EndDate

【讨论】:

但是我从前端得到@dates@name 作为逗号分隔的字符串,如上所示。那么如何将它们插入到临时表中呢? @MAK 我在您最初的尝试中看到您正在执行基于 XML 的内联拆分器。至少你应该把它变成一个内联 TVF,在这种情况下,它可以用来代替“SQL#.String_Split4k”而无需其他更改。但是继续使用基于 SQLCLR 的拆分器也没有什么坏处,因为它们是最快的 并且 如果您使用特殊的 XML 字符,则不会像基于 XML 的方法那样存在编码问题喜欢:&lt;"&amp; @MAK 当前数据库是否与安装 SQL# 的数据库相同?如果没有,您需要将函数的名称完全限定为:[dbname].SQL#.String_Split4K() 是的!我得到了它。非常感谢你陪我这么久。 @MAK 这是一个单独的问题。无论如何,我无法完全提供帮助,但您应该打开一个新问题并在此处添加带有该 URL 的评论。我可以说我刚刚在PostgreSQL中找到了一个内置的拆分功能:regexp_split_to_table。

以上是关于使用 SQL Server 2008 R2 的动态案例语句的主要内容,如果未能解决你的问题,请参考以下文章

windows 2012 r2怎么安装sql server 2008 r2

sql server2008升级到2008 R2出现问题

windows server2012 r2能安装sqlserver2008 R2吗

sql server 2008 r2 sp1 怎么看版本

win2012 server r2 怎么打开安装的sql2008

sql 2008 r2 在sql 2008上兼容么