从列表中选择子记录的记录

时间:2010-06-26 19:25:47

标签: sql tsql stored-procedures

问题

我正在尝试编写一个存储过程来选择 NewsItem 记录列表,其中每个 NewsItem 都包含所有类别一个列表。如果列表为空,则应返回所有新闻项。

NewsItem     NewsItemCategories     Category
--------     ------------------     --------
NewsID       NewsID                 CategoryID
Post         CategoryID             CategoryName

我将逗号分隔的类别名称列表传递给我的存储过程,并创建了一个返回这些类别的表的函数。

exec sp_GetNewsItems 'sport,football,hockey'

EntityNameColumn - table returned from my function BuildStringTable
----------------
sport
finance
history

我尝试过什么

select NI.NewsID, NI.Post
from NewsItem NI
where (@pCategories = '' or
    (select COUNT(*)
    from NewsItemCategories NIC
    inner join Category C on NIC.CategoryID = C.CategoryID
    inner join BuildStringTable(@pCategories) CT on C.CategoryName = CT.EntityNameColumn
where NIC.NewsID = NI.NewsID) > 0)

问题

如果您将单个类别名称传递给它,则查询有效,但是当您传递多个类别名称时,该查询不起作用。在上面的示例查询中,这应返回包含至少,类别运动,足球,曲棍球的NewsItem。

1 个答案:

答案 0 :(得分:1)

如果您使用的是sql 2005或更高版本,则可以使用EXCEPT运算符查找包含所有必需类别的新闻项。或者更准确地说,在新闻项目类别名称集合中找不到的类别列表中没有名称的新闻项目。

select NI.NewsID, NI.Post
from NewsItem NI
where (@pCategories = '' or
    NOT EXISTS (select EntityNameColumn FROM BuildStringTable(@pCategories) 
        EXCEPT 
              Select CategoryName FROM NewsItem ni 
              join NewsItemCategories nic ON ni.NewsID=nic.NewsID
              join Category c ON c.CategoryID = nic.CategoryID 
        WHERE ni.NewsID=NI.NewsID))

要在没有EXCEPT运算符的情况下执行此操作,请执行以下操作:

where (@pCategories = '' or
    NOT EXISTS (select EntityNameColumn FROM BuildStringTable(@pCategories) ct 
        LEFT OUTER JOIN 
              (Select CategoryName FROM NewsItem ni 
              join NewsItemCategories nic ON ni.NewsID=nic.NewsID
              join Category c ON c.CategoryID = nic.CategoryID
              WHERE ni.NewsID=NI.NewsID) nicn
        WHERE nicn.CategoryName IS NULL)