我正在使用MS SQL作为数据库构建一个简单的新闻站点。作者可以标记每个新闻项以对内容进行分类。我有一个页面,其中列出了与特定标签相关的所有标题,例如
www.example.org/tag/tag1
Headline 1
Headline 2
...
在该页面上,我还想显示与特定新闻项相关的所有其他标签,如下所示:
www.example.org/tag/tag1
Headline 1
[tag1] [tag2] -- show all related tags to each news item
Headline 2
[tag1] [tag3]
我认为我需要使用SQL STUFF和sub select,但是它不能按预期工作。
当我在下面运行SQL代码时,我得到以下信息:
Headline 1 computer, computer, business, general
Headline 2 computer, computer, business, general
但是我真正想要的是:
Headline 1 computer, business
Headline 2 computer, general
我的SQL有什么问题?
-- create table structure
create table #news (
newsid int,
title nvarchar(256)
)
create table #tags (
tagid int,
title nvarchar(128)
)
create table #newstags (
newsid int,
tagid int
)
-- load data
insert into #news values (1,'Headline 1')
insert into #news values (2,'Headline 2')
insert into #tags values (1,'computer')
insert into #tags values (2,'business')
insert into #tags values (3,'general')
insert into #newstags values (1,1) -- Headline 1, computer
insert into #newstags values (1,2) -- Headline 1, business
insert into #newstags values (2,1) -- Headline 2, computer
insert into #newstags values (2,3) -- Headline 2, general
declare @tagid int = 1
-- select results
select
NewsId
,Title
,STUFF(
(
SELECT
', ' + CAST(title AS nvarchar(64)) + ' [tagid:' + CAST(TagId AS nvarchar(64))+']' [text()]
FROM
(
SELECT
n.NewsId
,nt.TagId
,t.title
FROM #news n
INNER JOIN #newstags nt ON n.newsid = nt.newsid
INNER JOIN #tags t ON nt.tagId = t.TagId
WHERE n.newsid IN
(SELECT #newstags.newsid FROM #newstags WHERE tagid = @tagid)
) AS TempTable
FOR XML PATH(''), TYPE
).value('.','nvarchar(max)'),1,2,''
) AS TagsCombined
from #news
-- clean up
drop table #news
drop table #tags
drop table #newstags
答案 0 :(得分:1)
您的子查询有点复杂,并且与主查询没有关联。
这是修订版(我在代码中做了一些更改的地方包括了一些备注):
SELECT
n.NewsId
,Title
,STUFF(
(
SELECT
-- title is already nvarchar, no need to cast
-- TagId is an int - the maximum number of chars needed is 11
-- (enough to cover it's minimum value including the minus sign)
', ' + title + ' [tagid:' + CAST(TagId AS nvarchar(11))+']' [text()]
FROM
(
SELECT
nti.NewsId
,nti.TagId
,t.title
-- no need to select from #news here as well
FROM #newstags AS nti
INNER JOIN #tags AS t
ON nti.tagId = t.TagId
-- here's the relation to the main query
WHERE nti.newsid = n.newsid
--If you want all tags except the main one unremark the next row:
-- AND t.TagId <> @TagId
) AS TempTable
FOR XML PATH(''), TYPE
).value('.','nvarchar(max)'),1,2,''
) AS TagsCombined
FROM #news AS n
INNER JOIN #newstags AS nto ON n.NewsId = nto.NewsId
WHERE nto.TagId = @TagId