【问题标题】:How to use MS SQL STUFF with subselect?如何将 MS SQL STUFF 与子选择一起使用?
【发布时间】:2019-02-25 15:34:07
【问题描述】:

我正在使用 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

【问题讨论】:

  • 继续发布适当的样本数据和预期结果的方法!

标签: sql sql-server subquery


【解决方案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

【讨论】:

  • 感谢您的快速回答。我需要在 where-clause 的某个地方传递 @tagId ,该位置是 /tag/tag1 url。查询中缺少此参数?
  • 完美运行,感谢您也包含代码优化!谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 2016-05-27
  • 2021-09-25
  • 1970-01-01
相关资源
最近更新 更多