SELECT..CASE - 重构T-SQL

时间:2010-06-10 03:05:33

标签: tsql sql-server-2008

我是否可以针对每种情况将以下SQL CASE语句重构为单个?

SELECT 
  CASE RDV.DOMAIN_CODE  WHEN 'L' THEN CN.FAMILY_NAME  ELSE NULL END AS [LEGAL_FAMILY_NAME],
  CASE RDV.DOMAIN_CODE  WHEN 'L' THEN CN.GIVEN_NAME  ELSE NULL END AS [LEGAL_GIVEN_NAME],
  CASE RDV.DOMAIN_CODE  WHEN 'L' THEN CN.MIDDLE_NAMES  ELSE NULL END AS [LEGAL_MIDDLE_NAMES],
  CASE RDV.DOMAIN_CODE  WHEN 'L' THEN CN.NAME_TITLE  ELSE NULL END AS [LEGAL_NAME_TITLE],

  CASE RDV.DOMAIN_CODE  WHEN 'P' THEN CN.FAMILY_NAME  ELSE NULL END AS [PREFERRED_FAMILY_NAME],
  CASE RDV.DOMAIN_CODE  WHEN 'P' THEN CN.GIVEN_NAME  ELSE NULL END AS [PREFERRED_GIVEN_NAME],
  CASE RDV.DOMAIN_CODE  WHEN 'P' THEN CN.MIDDLE_NAMES  ELSE NULL END AS [PREFERRED_MIDDLE_NAMES],
  CASE RDV.DOMAIN_CODE  WHEN 'P' THEN CN.NAME_TITLE  ELSE NULL END AS [PREFERRED_NAME_TITLE]

FROM dbo.CLIENT_NAME CN
JOIN dbo.REFERENCE_DOMAIN_VALUE RDV 
ON CN.NAME_TYPE_CODE = RDV.DOMAIN_CODE AND RDV.REFERENCE_DOMAIN_ID = '7966'

4 个答案:

答案 0 :(得分:1)

如果RDV.DOMAIN_COD只能通过'P'或'L'使用NULLIf。它更干净。

NULLIF ( expression , expression )

NULLIF 等效于搜索到的CASE表达式,其中两个表达式相等,结果表达式为NULL。

SELECT
NullIf('P', RDV.DOMAIN_CODE) AS [LEGAL_FAMILY_NAME],
...
NullIf('L', RDV.DOMAIN_CODE) AS [PREFERRED_FAMILY_NAME],
...

答案 1 :(得分:1)

不,您需要8个单独的语句case,其他此类变体只能在select中用于修改单个列的结果,而不是一系列列。

答案 2 :(得分:1)

由于CASE表达式返回单个值,因此不能使8个CASE表达式返回8个值,并使单个CASE表达式返回所有8个值。

答案 3 :(得分:0)

没有案例的效率较低的替代方案:

SELECT LEGAL_FAMILY_NAME, LEGAL_GIVEN_NAME, LEGAL_MIDDLE_NAMES, LEGAL_NAME_TITLE,
       PREFERRED_FAMILY_NAME, PREFERRED_GIVEN_NAME, PREFERRED_MIDDLE_NAMES, PREFERRED_NAME_TITLE
FROM dbo.REFERENCE_DOMAIN_VALUE RDV
LEFT OUTER JOIN
  ( SELECT
      NAME_TYPE_CODE, 
      FAMILY_NAME AS [LEGAL_FAMILY_NAME],
      GIVEN_NAME AS [LEGAL_GIVEN_NAME],
      MIDDLE_NAMES AS [LEGAL_MIDDLE_NAMES],
      NAME_TITLE AS [LEGAL_NAME_TITLE]
    FROM dbo.CLIENT_NAME
    WHERE NAME_TYPE_CODE = 'L') LN ON RDV.DOMAIN_CODE = LN.NAME_TYPE_CODE
LEFT OUTER JOIN
  ( SELECT
      NAME_TYPE_CODE, 
      FAMILY_NAME AS [PREFERRED_FAMILY_NAME],
      GIVEN_NAME  AS [PREFERRED_GIVEN_NAME],
      MIDDLE_NAMES AS [PREFERRED_MIDDLE_NAMES],
      NAME_TITLE AS [PREFERRED_NAME_TITLE]
    FROM dbo.CLIENT_NAME
    WHERE NAME_TYPE_CODE = 'P') PN ON RDV.DOMAIN_CODE = PN.NAME_TYPE_CODE
  WHERE RDV.REFERENCE_DOMAIN_ID = '7966'

您还可以使用包含所有8列的临时表或表变量,然后执行两次插入。你也可以使用UNION ALL。我的猜测是8个案例陈述是最有效的方式。如果你有一些钥匙,你会想要某种类型的ClientID,法定名称,首选名称,那么你将在一个案件或东西周围包裹一个MAX,并通过ClientID分组......

您可以使用syscols / INFORMATION_SCHEMA.columns生成SQL脚本,每个列有两个案例,'CASE WHEN DOMAIN_CODE =''P''THEN'+ COLUMN_NAME +'ELSE NULL END PREFERRED_'+ COLUMN_NAME,然后是另一个L.你可以做一个循环,这样相同的代码对P执行一次,对L运行一次,然后将其调到一个循环。然后你可以直接EXEC字符串,或者打印它并将它放入你的SQL脚本中。无论如何只需8列我就会剪切/粘贴案例陈述......

但总的来说,T-SQL仅限于能够通过列进行eaches。您可以使用代码生成器(以t-sql或其他编程语言完成)生成脚本,或者以其他方式重新考虑您的问题。但很多时候,通过重复剪切/粘贴代码可以获得更好的性能。很多时候编写外部代码生成器的麻烦是不值得的(即只有8个案例语句)。