1

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

5 回答 5

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

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

于 2012-07-29T13:50:10.570 回答
0

可能不是。

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

我能想到的唯一可能性是更新您的存储过程/函数以允许空值,这样您就可以摆脱所有ISNULLs. 这是一个解释存储过程的链接。

于 2012-07-27T15:01:05.640 回答
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 列。

于 2012-07-27T17:29:22.737 回答
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

如果这些是您选择的唯一字段,它肯定会看起来更干净。但是我很确定我没有看到你的整个代码,所以这可能不会给你你想要的东西。

于 2012-07-27T17:33:26.387 回答
0

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

于 2012-07-27T21:34:32.863 回答