包含多行的SQL Case When语句

包含多行的SQL Case When语句,sql,sql-server-2005,case-when,Sql,Sql Server 2005,Case When,有没有办法使这个SQL更小 CASE WHEN @contentType = 'PrimaryBannerItem' THEN [dbo].[DeathStar_GetContentLink] (@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) ELSE

有没有办法使这个SQL更小

CASE
                    WHEN @contentType = 'PrimaryBannerItem' THEN
                        [dbo].[DeathStar_GetContentLink]         (@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, ''))

                    ELSE

                        [dbo].[DeathStar_GetContentImagePath](ISNULL(a.mimetype, ''), ISNULL(c.image, ''), ISNULL(l.filename, ''))
                END AS [Image],

                CASE
                    WHEN @contentType = 'PrimaryBannerItem' THEN
                         dbo.DeathStar_GetMetadataValue(c.content_id, @urlMetadataId)


                    ELSE

                        [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, ''))
                END AS Link,
让它看起来更像

CASE
    WHEN @contentType = 'PrimaryBannerItem' THEN
        [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Image]
        dbo.DeathStar_GetMetadataValue(c.content_id, @urlMetadataId) as [Link]
    ELSE
        [dbo].[DeathStar_GetContentImagePath](ISNULL(a.mimetype, ''), ISNULL(c.image, ''), ISNULL(l.filename, '')) as [Image]
        [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Link]
END
正如您所见,它使代码更具可读性,减少了使用的行数,避免了冗余。

可能不是

您在第二个代码块中建议的方式将不起作用。CASE是一条语句,只能用于返回单个列的值。这就是为什么将案例的结果定义为列,但不能在案例语句中定义列。这就解释了

我能想到的唯一可能性是更新存储过程/函数以允许空值,这样就可以去掉所有isNull。为存储过程解释这一点。

可能不是

您在第二个代码块中建议的方式将不起作用。CASE是一条语句,只能用于返回单个列的值。这就是为什么将案例的结果定义为列,但不能在案例语句中定义列。这就解释了


我能想到的唯一可能性是更新存储过程/函数以允许空值,这样就可以去掉所有isNull。为存储过程解释这一点。

不确定这是否更好,但如果不重复整个查询或使用重复的大小写,可能没有其他选项。。。什么时候其他的每个列的表达式,如示例中所示:

SELECT
  …
  COALESCE(choice1.Image, choice2.Image) AS Image,
  COALESCE(choice1.Link , choice2.Link ) AS Link,
  …
FROM
  …
OUTER APPLY (
  SELECT
    [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Image],
    dbo.DeathStar_GetMetadataValue(c.content_id, @urlMetadataId) as [Link]
  WHERE @contentType = 'PrimaryBannerItem'
) AS choice1
OUTER APPLY (
  SELECT
    [dbo].[DeathStar_GetContentImagePath](ISNULL(a.mimetype, ''), ISNULL(c.image, ''), ISNULL(l.filename, '')) as [Image],
    [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Link]
  WHERE @contentType <> 'PrimaryBannerItem'
    /* or, perhaps, "WHERE @contentType = 'something else'" */
) AS choice2
WHERE
  …

在两个外部应用程序之间,只有一个可以返回一行,另一个将始终返回一个空行集,其列将相应地计算为NULL。这意味着您可以使用COALESCE返回正确的结果:只需按必要的顺序指定相应的列,就会返回第一个非空的列。

不确定这是否更好,但如果不重复整个查询或使用重复的大小写,可能就没有其他选项了。。。什么时候其他的每个列的表达式,如示例中所示:

SELECT
  …
  COALESCE(choice1.Image, choice2.Image) AS Image,
  COALESCE(choice1.Link , choice2.Link ) AS Link,
  …
FROM
  …
OUTER APPLY (
  SELECT
    [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Image],
    dbo.DeathStar_GetMetadataValue(c.content_id, @urlMetadataId) as [Link]
  WHERE @contentType = 'PrimaryBannerItem'
) AS choice1
OUTER APPLY (
  SELECT
    [dbo].[DeathStar_GetContentImagePath](ISNULL(a.mimetype, ''), ISNULL(c.image, ''), ISNULL(l.filename, '')) as [Image],
    [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Link]
  WHERE @contentType <> 'PrimaryBannerItem'
    /* or, perhaps, "WHERE @contentType = 'something else'" */
) AS choice2
WHERE
  …

在两个外部应用程序之间,只有一个可以返回一行,另一个将始终返回一个空行集,其列将相应地计算为NULL。这意味着您可以使用COALESCE返回正确的结果:只需按必要的顺序指定相应的列,就会返回第一个非空的列。

这个解决方案可行吗

-- First case
IF @contentType = 'PrimaryBannerItem' BEGIN
    SELECT [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Image],
    dbo.DeathStar_GetMetadataValue(c.content_id, @urlMetadataId) as [Link]

-- Second case
END ELSE BEGIN
    SELECT [dbo].[DeathStar_GetContentImagePath](ISNULL(a.mimetype, ''), ISNULL(c.image, ''), ISNULL(l.filename, '')) as [Image],
    [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Link]
END

如果这些是您选择的唯一字段,那么它看起来肯定会更干净。但是,我很确定我没有看到您的全部代码,因此这可能无法完全满足您的需求。

这个解决方案可行吗

-- First case
IF @contentType = 'PrimaryBannerItem' BEGIN
    SELECT [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Image],
    dbo.DeathStar_GetMetadataValue(c.content_id, @urlMetadataId) as [Link]

-- Second case
END ELSE BEGIN
    SELECT [dbo].[DeathStar_GetContentImagePath](ISNULL(a.mimetype, ''), ISNULL(c.image, ''), ISNULL(l.filename, '')) as [Image],
    [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Link]
END

如果这些是您选择的唯一字段,那么它看起来肯定会更干净。但是,我很确定我没有看到您的全部代码,因此这可能无法提供您想要的内容。

否。CASE表达式返回一个标量,即单个值。它不能返回两个值;它不能返回两列的值。

否。大小写表达式返回一个标量,即单个值。它不能返回两个值;它不能为两列返回值。

如果两种情况下返回的结果集相同,也许您可以玩一个小把戏:

-- This query will return data only when @contentId = 'PrimaryBannerItem'
SELECT
  [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Image]
  ,dbo.DeathStar_GetMetadataValue(c.content_id, @urlMetadataId) as [Link]
  ,OtherFields
FROM
  YourTables
WHERE
  (@contentId = 'PrimaryBannerItem')
  -- Other WHERE clauses here

UNION ALL

-- This query will return data only when @contentId <> 'PrimaryBannerItem'
SELECT
  [dbo].[DeathStar_GetContentImagePath](ISNULL(a.mimetype, ''), ISNULL(c.image, ''), ISNULL(l.filename, '')) as [Image]
  ,[dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Link]
  ,OtherFields
FROM
  YourTables
WHERE
  (@contentId <> 'PrimaryBannerItem')
  -- Other WHERE clauses
这样,您就不需要使用任何IF、CASE等


注意:如果您开始遇到更复杂的条件,例如依赖于其他参数组合的值,这可能不是最有效的方法,无论是在性能方面,还是更重要的是在维护方面。

如果在这两种情况下返回的结果集相同,也许您可以玩一个小把戏:

-- This query will return data only when @contentId = 'PrimaryBannerItem'
SELECT
  [dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Image]
  ,dbo.DeathStar_GetMetadataValue(c.content_id, @urlMetadataId) as [Link]
  ,OtherFields
FROM
  YourTables
WHERE
  (@contentId = 'PrimaryBannerItem')
  -- Other WHERE clauses here

UNION ALL

-- This query will return data only when @contentId <> 'PrimaryBannerItem'
SELECT
  [dbo].[DeathStar_GetContentImagePath](ISNULL(a.mimetype, ''), ISNULL(c.image, ''), ISNULL(l.filename, '')) as [Image]
  ,[dbo].[DeathStar_GetContentLink](@contentId, c.content_id, @pageCollectionId, ISNULL(l.filename, '')) as [Link]
  ,OtherFields
FROM
  YourTables
WHERE
  (@contentId <> 'PrimaryBannerItem')
  -- Other WHERE clauses
这样,您就不需要使用任何IF、CASE等


注意:如果您开始遇到更复杂的条件,例如依赖于其他参数组合的值,这可能不是最有效的方法,无论是在性能方面,还是更重要的是在维护方面。

您是否正在寻找一种工具来为您格式化T-SQL?如果是这样的话,我已经使用SQLPrompt好几年了,并且对它相当满意。我认为使用同义词可以做到这一点。您是否正在寻找一种可以为您格式化T-SQL的工具?如果是这样的话,我已经使用SQLPrompt好几年了,并且对它相当满意。我认为使用同义词可以做到这一点:不尝试去除null,只需同时将值返回到2列中,而不必生成2个不同的大小写。不尝试去除null,只需同时将值返回到2列中,而不必生成2个不同的大小写。即使它们是返回的唯一字段,这是行不通的,因为有些参数是列引用或包含列引用的表达式。明白-我想,总的来说,如果条件列数较高,则希望在IF语句中进行两次完全选择;如果非条件列数较高,则希望对所有内容进行两次完全选择。即使它们是返回的唯一字段,这也不起作用,因为某些参数是列引用或
包含列引用的按。明白-我认为,总的来说,如果条件列的数量较多,您可能希望在IF语句中执行两次完整选择,如果非条件列的数量较多,则希望对所有内容执行CASE列。