Sql Server - 有没有办法在Select中使用`Concat` nvarchar列`Aggregate functions`

时间:2014-10-10 10:48:35

标签: sql sql-server

你好我有调用标签的表,在标签表中我有2列(QuestionID int,Tag nvachar(100))
我想在一列中选择包含所有标签的问题,如下所示

QuestionID  Tag
----------  ----
1   Math
1   Integral
2   Physics


QuestionID  QuestionText
----------  -----------
1       What is 2*2?
2       What is Quantom roles?

QuestionID  QuestionText        Tags
----------  -----------     -------
1       What is 2*2?        Math, Integral
2       What is Quantom roles?  Physics

任何人都可以帮助我使用scalar value function

6 个答案:

答案 0 :(得分:1)

CREATE TABLE #temp
  (
     QuestionID INT,
     Tag        NVARCHAR(100)
  )

INSERT INTO #temp
            (QuestionID,Tag)
VALUES     (1,N'Math'),
            (1,N'Integral'),
            (2,N'Physics')

CREATE TABLE #temp1
  (
     QuestionID   INT,
     QuestionText NVARCHAR(100)
  )

INSERT INTO #temp1
            (QuestionID,QuestionText)
VALUES     (1,N'What is 2*2?'),
            (2,'What is Quantom roles?')

SELECT h.QuestionID,
       h.QuestionText,
       Stuff((SELECT ', ' + CONVERT(VARCHAR, b.TAG)
              FROM   #temp b
              WHERE  b.QuestionID = h.QuestionID
              FOR XML PATH('')), 1, 2, '')
FROM   #temp t
       JOIN #temp1 h
         ON t.QuestionID = h.QuestionID
GROUP  BY h.QuestionID,
          h.QuestionText 

答案 1 :(得分:1)

SELECT q.QuestionText
    ,STUFF((
            SELECT ', ' + t2.Tag
            FROM Tags t2
            WHERE t1.QuestionID = t2.QuestionID
            ORDER BY t2.Tag
            FOR XML PATH('')
                ,TYPE
            ).value('.', 'varchar(max)'), 1, 2, '') AS Tag
FROM Questions q
INNER JOIN Tags t1
    ON q.QuestionID = t1.QuestionID
GROUP BY q.QuestionText
    ,t1.QuestionID

工作示例:http://sqlfiddle.com/#!3/e8f0f/7

答案 2 :(得分:1)

尝试子查询以逗号分隔值连接列数据,如下所示:

SELECT  [QuestionID],
        [QuestionText],
        STUFF(( SELECT  ',' + [Tag]
        FROM    [dbo].[Tags]
        WHERE   [QuestionID] = [Question].[QuestionID]
        FOR XML PATH ('')), 1, 1, '') AS [Tags]
FROM [dbo].[Question]

<强> SQL Fiddle Demo

答案 3 :(得分:1)

试试这个

create function fn_comma (@question_id int)
returns varchar(100)
as
begin
declare @value varchar(100)
set @value=(SELECT  top 1 STUFF((SELECT ', ' + CAST(Value AS VARCHAR(10)) [text()]
         FROM Tags
         WHERE ID = t.ID
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') List_Output
FROM Tags
--where id=1
GROUP BY ID)
return @value
end

答案 4 :(得分:1)

有两种方法可以解答这个问题:

  1. 可以像其他答案一样使用查询,但这仅适用于一个表。
  2. 为此创建clr aggregate function,如下面的代码(我在C#中的代码) 该解决方案适用于所有表格且易于使用,
    仅在sql server
  3. 中使用:select Concat(column) from Table
    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Data.SqlTypes;
    using Microsoft.SqlServer.Server;
    using System.Text;
    
    
    [Serializable]
    [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined, IsInvariantToDuplicates = false, IsInvariantToNulls = true, IsInvariantToOrder = false, IsNullIfEmpty = true, MaxByteSize = -1)]
    public struct Concat : IBinarySerialize
    {
    
        public void Init()
        {
            SB = new StringBuilder();
        }
    
        public void Accumulate(SqlString Value)
        {
            if (Value.IsNull)
                return;
            if (SB.Length > 0)
                SB.Append("\n");
            SB.Append(Value);
        }
    
        public void Merge(Concat Group)
        {
            if (SB.Length > 0 && Group.SB.Length > 0)
                SB.Append("\n");
            SB.Append(Group.SB.ToString());
        }
    
        public SqlString Terminate()
        {
            return new SqlString(SB.ToString());
        }
    
        // This is a place-holder member field
        StringBuilder SB;
    
        public void Read(System.IO.BinaryReader r)
        {
            SB = new StringBuilder(r.ReadString());
        }
    
        public void Write(System.IO.BinaryWriter w)
        {
            w.Write(SB.ToString());
        }
    
    }
    

答案 5 :(得分:0)

尝试以下想法。您只需要将其重写为函数,然后它将返回问题ID的所有标记:

declare @function_in_questionid_para as @int

with std as 
(select *,ROW_NUMBER() over(partition by QuestionID order by QuestionID,tag) as dd from #temp)
 select * #temp3 into from std
 declare @counter as int
 set @counter = (select count(*) from #temp where QuestionID = @function_in_questionid_para as @int)
 declare @c as int = 1

 declare @tags as varchar(200) = ''
 while (@c <= @counter)
 begin
 if (@c > 1)  set @tags = @tags + ', ' 
 set @tags = @tags + (select tag from #temp3 where QuestionID = @function_in_questionid_para as @int and dd = @c)
 set @c = @c + 1
 end
 print @tags