我写了一个有超过 100 个选项的 case 语句,在一个简单的查询中,我在 4 个地方使用了相同的语句。
相同的查询两次,它们之间有一个联合,但也在进行计数,因此 group by 也包含 case 语句。
这是为了重新标记一些公司名称,其中同一公司的不同记录拼写不同。
我试图将变量声明为 VarChar(MAX)
declare @CaseForAccountConsolidation varchar(max)
SET @CaseForAccountConsolidation = 'CASE
WHEN ac.accountName like ''AIR NEW Z%'' THEN ''AIR NEW ZEALAND''
WHEN ac.accountName LIKE ''AIR BP%'' THEN ''AIR BP''
WHEN ac.accountName LIKE ''ADDICTION ADVICE%'' THEN ''ADDICTION ADVICE''
WHEN ac.accountName LIKE ''AIA%'' THEN ''AIA''
...
当我在我的 select 语句中使用它时 - 查询只是将 case 语句作为文本返回并且没有对其进行评估。
我也无法在组中使用它 - 我收到以下错误消息:
Each GROUP BY expression must contain at least one column that is not an outer reference.
理想情况下,我希望将 CASE 放在一个地方 - 这样我就没有机会更新一行而不在其他地方复制它。
有没有办法做到这一点?
我对其他方式持开放态度(比如可能是一个功能 - 但我不知道如何像这样使用它们)
这是我目前正在使用的 SELECT 示例
SELECT
SUM(c.charge_amount) AS GSTExcl
,dl.FirstDateOfMonth AS MonthBilled
,dl.FirstDateOfWeek AS WeekBilled
,CASE
WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
ELSE ac.accountName
END AS accountName
,dl.FinancialYear
,CONVERT(Date,c.date_charged) AS date_charged
FROM [accession] a
LEFT JOIN account_code ac ON a.account_code_id = ac.account_code_id
LEFT Join charge c ON a.accession_id = c.accession_id
LEFT JOIN dateLookup dl ON convert(date,c.date_charged) = dl.date
WHERE a.datecreated = CONVERT(DATE,now())
GROUP BY
dl.FirstDateOfMonth
,dl.FinancialYear
,dl.FirstDateOfWeek
,CONVERT(Date,c.date_charged)
,CASE
WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
ELSE ac.accountName
END
UNION
SELECT
SUM(c.charge_amount) AS GSTExcl
,dl.FirstDateOfMonth AS MonthBilled
,dl.FirstDateOfWeek AS WeekBilled
,CASE
WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
ELSE ac.accountName
END AS accountName
,dl.FinancialYear
,CONVERT(Date,c.date_charged) AS date_charged
FROM [accession] a
LEFT JOIN account_code ac ON a.account_code_id = ac.account_code_id
LEFT Join charge c ON a.accession_id = c.accession_id
LEFT JOIN dateLookup dl ON convert(date,c.date_charged) = dl.date
WHERE a.datecreated = DATEADD(YEAR,-1,CONVERT(DATE,now()))
GROUP BY
dl.FirstDateOfMonth
,dl.FinancialYear
,dl.FirstDateOfWeek
,CONVERT(Date,c.date_charged)
,CASE
WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
ELSE ac.accountName
END
此 UNION 的目的是返回某个时间段的所有数据,以及返回同一时间段之前 12 个月的数据
编辑:添加了丢失的“CATCH-ALL”
EDIT2:添加了 UNION 语句的第二个½
EDIT3:更正了 GROUP BY 以包含一些其他必要的元素
将数据放入表中
并加入其中。
这样,您就可以避免在多个地方保持数据最新。只需
COALESCE
在需要的地方使用即可。VIEW
您可以根据其他建议将其合并到 CTE 或s 中。消除 CASE 表达式重复的一种简单方法是像这样使用 CROSS APPLY:
在 CROSS APPLY 的帮助下,您可以为 CASE 表达式指定一个名称,以便可以在语句中的任何位置引用它。它之所以有效,是因为严格来说,您是在嵌套SELECT中定义计算列- CROSS APPLY 之后的 FROM-less SELECT。
这与引用派生表的别名列相同——从技术上讲,这个嵌套的 SELECT 就是。它既是相关子查询,又是派生表。作为关联子查询,它允许引用外部范围的列,作为派生表,它允许外部范围引用它定义的列。
对于使用相同 CASE 表达式的 UNION 查询,您必须在每个分支中定义它,除了使用完全不同的替换方法而不是 CASE 之外,没有解决方法。但是,在您的特定情况下,可以在没有 UNION 的情况下获取结果。
两条腿仅在 WHERE 条件上有所不同。一个有这个:
另一个是:
你可以像这样组合它们:
并将其应用于此答案开头的修改后的 SELECT 。
我认为如果您需要在多个地方重复使用它的另一种选择,内联表值函数将是一个不错的选择。
您的选择将是这样的。
另外,我还没有对此进行测试,代码的性能也应该确定。
EDIT1:我认为 andriy 已经给出了一个使用交叉应用来编辑代码的方法。好吧,这个可以集中,因为函数中的任何更改都会反映在所有代码中,因为您在代码的其他部分重复相同的内容。
我会用 a
VIEW
来做你想做的事情。当然,您可以更正基础数据,但经常在此站点上提出问题的人(顾问/dbas/)无权执行此操作。使用aVIEW
可以解决这个问题!我还利用了这个UPPER
功能——在这种情况下解决错误的一种廉价方法。现在,您只需声明
VIEW
一次,就可以在任何地方使用它!这样,您只有一个存储和运行数据转换算法的地方,从而提高了系统的可靠性和稳健性。您还可以使用 CTE(公用表表达式) - 请参阅答案底部!
为了回答你的问题,我做了以下事情:
创建示例表:
插入几个示例记录:
VIEW
然后按照建议创建一个:然后,
SELECT
从您的VIEW
:结果:
瞧!
你可以在这里找到所有这些。
CTE
方法:与上述相同,除了
CTE
替换为VIEW
如下:结果是一样的。然后,您可以像对待
CTE
任何其他表一样对待 s -SELECT
仅用于 s!小提琴在这里可用。总的来说,我认为
VIEW
在这种情况下这种方法更好!嵌入式表
按照其他人的建议,跳过联合并
OR
在 where 中使用。