【问题标题】:Set variable to part of a SQL statement and use in a CASE WHEN scenario将变量设置为 SQL 语句的一部分并在 CASE WHEN 场景中使用
【发布时间】:2014-05-13 20:54:06
【问题描述】:

简介:

是否可以在包含 SQL 语句的存储过程中创建变量,然后在 CASE WHEN 语句中引用这些语句?

例如:

SET @Condition1 = (columnA = columnB AND columnC = 'hello')
SET @Function1 = (columnC + ' and ' + columnA + ' ' + columnB)

SELECT columnA, columnB, columnC, CASE WHEN @Condition1 THEN @Function1 END AS columnD
FROM SampleTable

完整说明:

我正在开发一个存储过程,该过程将在 SSRS 中用于显示邮件列表表。初始数据如下所示:

Salute    |    first_name    |    last_name    |    Salute2    |    firstname2    |    lastname2
Mr              John               Doe               Mrs               Jane            Doe
Dr              Steve              Smith             Mrs               Steph           Smithington
Mrs             Jill               Hill              Mr                Jack            Hill

最终有大约 30 种称呼组合,(先生和夫人、夫人和先生、博士和博士等)。我需要创建 2 个新列,FormalAddresseeFormalSalutation,它们根据看到的称呼组合格式化数据。这是最终结果的示例,请注意原始列仍然存在,为简洁起见,我只是不构建表格:

Sal|FN|LN|Sal2|FN2|LN2|        FormalAddressee                       |        FormalSalutation        
                           Mr and Mrs John Doe                               Mr John Doe
                           Dr Steve Smith and Mrs. Steph Smithington   Dr Steve Smith and Mrs. Steph Smithington
                           Mr. and Mrs. Jack Hill                            Mr Jack Hill

我最初开始的是一个巨大的 CASE WHEN 语句,看起来像这样,重复 30 次以覆盖 FormalAddressee 的每个称呼组合,然后再次覆盖 FormalSalutation,因为语句的 THEN 部分与2 列:

WHEN mem.salute = 'Mrs.' AND mem.salute2 = 'Mr.' AND dbo.Proper(mem.last_name) = dbo.Proper(lastname2) 
                     THEN (mem.salute2 + ' and ' + mem.salute + ' ' + dbo.Proper(firstname2) + ' ' + dbo.Proper(lastname2)) ... etc etc END AS FormalAddressee

这变得难以管理,特别是如果添加了新的称呼组合(而且我已经知道即将推出新的一组)。因为语句的THEN 部分是重复的,这意味着相同的格式公式可以用于多个称呼组合,我希望将其设置为一系列变量,以至少使其更清晰和更易于修改.

这是FormalAddressee 信息的示例,FormalSalutation 信息的示例类似:

DECLARE @FA1 nvarchar(300)
DECLARE @FA2 nvarchar(300)
...
DECLARE @FA10 nvarchar(300)

SET @FA1 = (salute2 + ' and ' + salute + ' ' + dbo.Proper(firstname2) + ' ' + dbo.Proper(lastname2))
SET @FA2 = (salute + ' and ' + salute2 + ' ' + dbo.Proper(first_name) + ' ' + dbo.Proper(last_name))
...
SET @FA10 = (dbo.Proper(first_name) + ' ' + dbo.Proper(last_name))

CREATE TABLE #AddressTable
([columns set up here])
INSERT INTO #AddressTable SELECT [existing columns],
CASE WHEN...END AS FormalAddressee,
CASE WHEN...END AS FormalSalutation
FROM AddressDataTable

然后,我将使用上表中所示的分解数据构建我的临时表,并创建新列并尝试将@FA 变量拉入CASE WHENTHEN 部分声明,但无济于事,坦率地说,我并不乐观这会奏效。

CASE  WHEN mem.salute = 'Mrs.' AND mem.salute2 = 'Mr.' AND dbo.Proper(mem.last_name) = dbo.Proper(lastname2) 
    THEN @FA1

当我去执行 SP 创建时,我收到一系列错误,指出 The multi-part identifier "salute2" could not be bound 的每一行 SET 语句。我理解为什么会出现此错误,因此我尝试将其转换为字符串,并用单引号括起来并添加更多单引号以容纳内部单引号,但是最终结果仅显示字符串而不是获取数据并合并它以获得正确的最终结果。

我也希望能够将称呼组合设置为变量,因为我可能会被要求根据看到的组合创建 6 或 7 列格式,所以最终会非常甜蜜:

CASE WHEN @SalCombo1 THEN @FA1 ... END AS FormalAddressee,
CASE WHEN @SalCombo1 THEN @FS1 ... END AS FormalSalutation

我是否真的过于复杂化并试图做一些不合理的事情,而不是仅仅输入所有完整的CASE WHEN 语句?我很乐意这样做,而且我可能会在研究这个并最终在 SO 上发布的时间内完成它,但我觉得必须有更好的方法来更有效地为我和我的继任者服务。

【问题讨论】:

    标签: sql reporting-services sql-server-2012


    【解决方案1】:

    如果您使用另一个中间临时表(或表变量),而不是将所有这些存储在变量中,该怎么办?如果我正确理解您的问题,这里的问题是,根据字段的顺序,您希望能够重新组织您的数据。因此,与其尝试将其存储在变量中,不如将数据移动到重新组织的中间表中?

    这是基于您的示例的尝试:

    CREATE TABLE #Intermediate (
      salute1 [datatype],
      salute2 [datatype],
      first1 [datatype],
      first2 [datatype],
      last1 [datatype],
      last2 [datatype]
    );
    
    /* @FA1 */ 
    INSERT INTO #Intermediate (salute1, salute2, first1, last1)
    SELECT salute2, salute, dbo.Proper(firstname2), dbo.Proper(lastname2)
    FROM [table]
    WHERE mem.salute = 'Mrs.' AND mem.salute2 = 'Mr.' AND dbo.Proper(mem.last_name) = dbo.Proper(lastname2);
    
    /* @FA2 */
    INSERT INTO #Intermediate (salute1, salute2, first1, last1)
    SELECT salute, salute2, dbo.Proper(first_name), dbo.Proper(last_name)
    FROM [table]
    WHERE [criteria]
    
    /* @FA10 */
    INSERT INTO #Intermediate (first1, last1)
    SELECT dbo.Proper(first_name), dbo.Proper(last_name)
    

    然后,您有一个排列良好的表,您可以使用一条语句将其中的内容移动到您的第二个临时表中。您无需担心数据位于错误的字段中,因为您已经重新排列。

    以下只是一个例子;这可能不是您需要的完整逻辑。

    CREATE TABLE #AddressTable
    ([columns set up here])
    
    INSERT INTO #AddressTable 
    SELECT COALESCE(salute1, '') + COALESCE(' and ' + salute2, '') 
           + first1 + ' ' + last1
           + COALESCE(first2 + ' ' + last2, '')
    FROM #Intermediate
    

    这仍然是一团糟,但我不确定你是否可以避免你需要的逻辑混乱。至少它比尝试使用不同的变量跟踪所有内容要干净一些。

    【讨论】:

    • 感谢您非常详细的回复!这是一个有趣的方法,我什至没有考虑过。尽管使用 SP 而不是视图至少允许我使用换行符、制表符和注释来发挥我的优势,但它看起来仍然很混乱。我会试一试(正确构建它需要一段时间)并报告回来。我仍然想知道我是否可以按照概要要求进行;有没有办法在 CASE WHEN 中使用带有 SQL 语句的变量?再次感谢
    • @BobbyScon AFAIK 这样做的唯一方法更加混乱——使用变量来构建动态 SQL 语句,然后在过程结束时执行这些语句。
    • 是的,这就是我所担心的。我以前为更简单的设置做过。我只是抱着希望有一些我不知道的魔法可以使这项工作;-)
    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多