SQL具有'CASE columnx IN(select statement)'的语句

时间:2014-03-16 02:15:26

标签: sql sql-server-2008-r2

如果我没有在CASE子句中添加HAVING u.urlid in (SELECT ... )语句,我有一个返回正确数据的SQL Server 2008 R2查询。

基本上,如果变量HAVING

,我希望以下查询返回SQL语句的@IDList = '0'部分中的所有内容

下面的语句在@IDList子句中由HAVING u.urlid in过滤并按预期工作,但我需要在HAVING子句中添加一些返回所有数据的内容FROM urlcat inner join URL ON URLCat.URLID = URL.URLID如果@IDList = '0'

declare @IDList NVARCHAR(MAX) = '0'
declare @Count INTEGER = 1
declare @RowIndex INTEGER = 0
declare @PageSize INTEGER = 1000000
declare @wordList NVARCHAR(MAX) = ''

Set @IDList = '110713'
Set @wordList = 'nova'  

SET NOCOUNT ON;
SELECT t2.URLID, t2.CategorySummary, t2.Title, t2.[Description], t2.URL 
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY COUNT(ws.equiv_word)) AS [ROW_NUMBER],
    u.URLID, CategorySummary = dbo.SQL_CLR_Aggregate(ws.word + ', ' + CAST(ws.[order] AS NVARCHAR) ),
    u.Title, u.[Description], u.URL 
    FROM URLCat uc inner join word_senses ws ON uc.CatID = ws.word_sense inner join URL u ON uc.URLID = u.URLID 
    GROUP BY u.urlid, u.Title, u.[Description], u.URL
    -- NOTE: This is the part I'm having issues with
    HAVING u.urlid in 
    (
      SELECT URLCat.URLID 
      FROM urlcat inner join URL ON URLCat.URLID = URL.URLID 
      WHERE CatID in (SELECT * FROM dbo.bigintlist_to_tbl(@IDList))
      GROUP BY urlcat.urlid 
      HAVING COUNT(DISTINCT catid)=@Count)
     )
     AS t2
 WHERE t2.[ROW_NUMBER] BETWEEN @RowIndex + 1 AND @RowIndex + @PageSize AND 
 (@wordList = '' OR (t2.Title like '%' + @wordList  + '%' OR t2.Description like '%' + @wordList  + '%'))
 ORDER BY t2.[ROW_NUMBER]

我已经尝试了以下case语句,我将其添加到HAVING子句中,但我会这样做:

HAVING u.urlid in 
    (
    CASE WHEN @IDList = '0' THEN u.urlid
    ELSE
    (SELECT URLCat.URLID 
    FROM urlcat inner join URL ON URLCat.URLID = URL.URLID 
    WHERE CatID in (SELECT * FROM dbo.bigintlist_to_tbl(@IDList))
    GROUP BY urlcat.urlid 
    HAVING COUNT(DISTINCT catid)=@Count) END
    )
) AS t2

但是,当我添加此CASE语句时,它会给我一个错误:

  

Msg 512,Level 16,State 1,Line 15
  子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

我可以确认该声明有效:

  • 如果我拥有CASE声明
  • 如果我(即返回所有内容)HAVING u.urlid in u.urlid
  • 如果我(即由@IDList过滤)

    HAVING u.urlid in ( SELECT URLCat.URLID FROM urlcat inner join URL ON URLCat.URLID = URL.URLID WHERE CatID in (SELECT * FROM dbo.bigintlist_to_tbl(@IDList)) GROUP BY urlcat.urlid HAVING COUNT(DISTINCT catid)=@Count))

但我需要做一个或另一个,具体取决于@IDList = '0'

任何人都可以给我一些选项或理由,说明我的CASE声明在HAVING条款中不起作用吗?

2 个答案:

答案 0 :(得分:3)

case不起作用,因为它只能产生单个值,而不是子查询的结果。

您可以在子查询中使用union来根据变量返回不同的结果:

HAVING u.urlid in (
  SELECT URLCat.URLID 
  FROM urlcat inner join URL ON URLCat.URLID = URL.URLID 
  WHERE CatID in (SELECT * FROM dbo.bigintlist_to_tbl(@IDList))
  GROUP BY urlcat.urlid 
  HAVING COUNT(DISTINCT catid)=@Count) and @IDList <> '0'
  UNION ALL
  SELECT u.urlid WHERE @IDList = '0'
)

答案 1 :(得分:1)

我会把它写成复合语句:

 HAVING @IDList = '0' or
        u.urlid in (SELECT URLCat.URLID 
                    FROM urlcat inner join
                         URL
                         ON URLCat.URLID = URL.URLID 
                    WHERE CatID in (SELECT * FROM dbo.bigintlist_to_tbl(@IDList))
                    GROUP BY urlcat.urlid 
                    HAVING COUNT(DISTINCT catid)=@Count) END
                   )
) AS t2

我认为逻辑更容易遵循这种方式。

请注意,您也可以在where子句而不是having子句中执行此操作。