将多行中的单个列连接到一个具有不同关键字的列中

时间:2013-01-29 10:37:49

标签: sql-server tsql common-table-expression

我有table条,其中有一列keywords存储标签或关键字

样本数据

Table Article
------------------------------------------
ID    keywords
------------------------------------------
1     one, two, three
2     four, five, six
3     seven, eight, three
4     one, two, three
5     twenty, hundred, one hundred one, one hundred two, seventy
6     seventy, three, two hundred 

如果我使用下面的CTE查询,那么它将连接一行中的所有关键字列,但另一方面也会获得重复的行,这是一个问题,因为我将有1000条带有数百个类似关键字的文章。 / p>

SELECT TOP 1 
    stuff(
    (
    select cast(',' as varchar(max)) + lower(Keywords)
    from art_Article a
    for xml path('')
    ), 1, 1, '') AS All_Keywords
FROM
    art_Articles G
ORDER BY
    G.ArticleKeywords ASC;

以上查询产生以单行

的结果
---------------------------------------------------
All_Keywords
----------------------------------------------------
one, two, three,four, five, six,seven, eight, three,one, two, three,twenty, hundred, one hundred one, one hundred two, seventy,seventy, three, two hundred 

从结果中可以明显看出它也显示重复的关键字no。时间,因为它存储在行中。他们是一种只能获得一次重复关键字的方式吗?

如果有人可以帮助我对其进行排序,将结果作为仅包含DISTINCT个关键字的单列,我将不胜感激。

3 个答案:

答案 0 :(得分:4)

我认为在将数据连接在一起之前,您必须首先将数据拆分为行。这将允许您在使用FOR XML PATH获取最终列表时获取不同的值。

以下是此流程的CTE版本:

;with cte (id, word, words) as
(
  select id,
    cast(left(keywords, charindex(',',keywords+',')-1) as varchar(50)) word,
         stuff(keywords, 1, charindex(',',keywords+','), '') words
  from article
  union all
  select id,
    cast(left(words, charindex(',',words+',')-1) as varchar(50)) word,
    stuff(words, 1, charindex(',',words+','), '') words
  from cte
  where words > ''
) 
select top 1 
    stuff((select distinct ', '+ rtrim(ltrim(word))
           from cte
           for xml path('')), 1, 1, '') AS All_Keywords
from cte

SQL Fiddle with Demo。结果如下:

|                                                                                                             ALL_KEYWORDS |
----------------------------------------------------------------------------------------------------------------------------
|  eight, five, four, hundred, one, one hundred one, one hundred two, seven, seventy, six, three, twenty, two, two hundred |

答案 1 :(得分:2)

相关子查询应该这样做:

SELECT G.ID,
    stuff(
    (
    select cast(',' as varchar(max)) + lower(Keywords)
    from art_Article a
    where a.id = g.id
    for xml path('')
    ), 1, 1, '') AS All_Keywords
FROM
    art_Articles G
ORDER BY
    G.ArticleKeywords ASC;

答案 2 :(得分:0)

其中一个解决方案是将结果与Split功能相结合。在其上运行带有DISTINCT的SQL语句。您可以根据需要进一步修改。我有测试&它对我有用。希望它能帮助其他人。

DECLARE @Keywords nvarchar(MAX)
SELECT TOP 1 @Keywords =
    stuff(
    (
    select cast(',' as varchar(max)) + lower(Keywords)
    from Article U
    for xml path('')
    ), 1, 1, '') 
FROM
    Articles G
ORDER BY
    G.ArticleKeywords ASC;

SELECT DISTINCT(VALUE) AS VALUE FROM [uf_SplitKeywords] (',', @Keywords)

分割功能代码

ALTER FUNCTION [dbo].[uf_SplitKeywords] 
   (  @DELIMITER VARCHAR(5), 
      @LIST      VARCHAR(MAX) 
   ) 
   RETURNS @TABLEOFVALUES TABLE 
      (  ROWID   int IDENTITY(1,1), 
         [VALUE] VARCHAR(MAX) 
      ) 
AS 
   BEGIN
   Declare @Pos int
   While LEN(@List) > 0
      begin
        Select @Pos=CHARINDEX(@Delimiter,@List,1)      
        if @Pos>0
           begin
             Insert into @TABLEOFVALUES ([Value]) Values (SubString(@List,1,@Pos -1))
             Select @LIST = STUFF(@List,1,@Pos ,'')
           end
        else  
            begin
            Insert into @TABLEOFVALUES ([Value]) Values (@List)
            Select @LIST =''
            end  
      end
   Return 
   End