SQL Case当多行语句时

时间:2012-07-27 14:17:31

标签: sql sql-server-2005 case-when

有没有办法让这个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

因为正如您所看到的,它使代码更具可读性,它减少了使用的行数并避免了冗余。

4 个答案:

答案 0 :(得分:1)

如果在两种情况下返回的结果集相同,也许你可以玩一个小技巧:

-- 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等。

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

答案 1 :(得分:0)

不确定这是否会更好,但是如果不必重复整个查询或对每个列使用重复的CASE ... WHEN ... ELSE ...表达式,可能没有其他选项,例如:

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
  …

在两个OUTER APPLY之间,只有一个可以返回一行,另一个将始终返回一个空行集,并且其列将相应地计算为NULL。这意味着你可以使用COALESCE返回“正确”的结果:只需按照必要的顺序指定相应的列,然后返回第一个非NULL的列。

答案 2 :(得分:0)

这个解决方案可行吗?

-- 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

如果这些是你选择的唯一领域,它肯定会看起来更干净。但是我很确定我没有看到你的整个代码,所以这可能无法满足你的需求。

答案 3 :(得分:0)

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