问题
我正在尝试编写一个存储过程来选择 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。
答案 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)