441

どうすれば入手できますか:

id       Name       Value
1          A          4
1          B          8
2          C          9

id          Column
1          A:4, B:8
2          C:9
4

22 に答える 22

608

CURSOR、WHILE ループ、またはユーザー定義関数は必要ありません

FOR XML と PATH を使用して創造性を発揮する必要があります。

[注: このソリューションは、SQL 2005 以降でのみ機能します。元の質問では、使用中のバージョンが指定されていませんでした。]

CREATE TABLE #YourTable ([ID] INT, [Name] CHAR(1), [Value] INT)

INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'A',4)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'B',8)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (2,'C',9)

SELECT 
  [ID],
  STUFF((
    SELECT ', ' + [Name] + ':' + CAST([Value] AS VARCHAR(MAX)) 
    FROM #YourTable 
    WHERE (ID = Results.ID) 
    FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
  ,1,2,'') AS NameValues
FROM #YourTable Results
GROUP BY ID

DROP TABLE #YourTable
于 2008-11-07T19:31:35.617 に答える
54

XMLパスを使用すると、期待どおりに完全に連結されません...「&」が「&」に置き換えられます また、混乱し<" and "> ます...おそらく他のいくつかのことですが、わかりません...しかし、これを試すことができます

私はこれの回避策に出くわしました...あなたは置き換える必要があります:

FOR XML PATH('')
)

と:

FOR XML PATH(''),TYPE
).value('(./text())[1]','VARCHAR(MAX)')

...またはNVARCHAR(MAX)それがあなたが使用しているものである場合。

SQL連結集計関数がないのはなぜですか? これはピタです。

于 2011-12-06T17:58:00.483 に答える
44

Kevin Fairchildの提案を、エンコードされたスペースと特殊なXML文字(、、)を含む文字列で機能するように変換しようとしたときに、いくつかの問題が発生しました&<>

私のコードの最終バージョン(元の質問には答えませんが、誰かに役立つかもしれません)は次のようになります。

CREATE TABLE #YourTable ([ID] INT, [Name] VARCHAR(MAX), [Value] INT)

INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'Oranges & Lemons',4)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'1 < 2',8)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (2,'C',9)

SELECT  [ID],
  STUFF((
    SELECT ', ' + CAST([Name] AS VARCHAR(MAX))
    FROM #YourTable WHERE (ID = Results.ID) 
    FOR XML PATH(''),TYPE 
     /* Use .value to uncomment XML entities e.g. &gt; &lt; etc*/
    ).value('.','VARCHAR(MAX)') 
  ,1,2,'') as NameValues
FROM    #YourTable Results
GROUP BY ID

DROP TABLE #YourTable

スペースを区切り文字として使用し、すべてのスペースをコンマに置き換えるのではなく、各値の前にコンマとスペースを追加STUFFして、最初の2文字を削除するために使用します。

XMLエンコーディングは、TYPEディレクティブを使用して自動的に処理されます。

于 2011-10-18T10:48:44.620 に答える
24

Sql Server 2005 以降を使用する別のオプション

---- test data
declare @t table (OUTPUTID int, SCHME varchar(10), DESCR varchar(10))
insert @t select 1125439       ,'CKT','Approved'
insert @t select 1125439       ,'RENO','Approved'
insert @t select 1134691       ,'CKT','Approved'
insert @t select 1134691       ,'RENO','Approved'
insert @t select 1134691       ,'pn','Approved'

---- actual query
;with cte(outputid,combined,rn)
as
(
  select outputid, SCHME + ' ('+DESCR+')', rn=ROW_NUMBER() over (PARTITION by outputid order by schme, descr)
  from @t
)
,cte2(outputid,finalstatus,rn)
as
(
select OUTPUTID, convert(varchar(max),combined), 1 from cte where rn=1
union all
select cte2.outputid, convert(varchar(max),cte2.finalstatus+', '+cte.combined), cte2.rn+1
from cte2
inner join cte on cte.OUTPUTID = cte2.outputid and cte.rn=cte2.rn+1
)
select outputid, MAX(finalstatus) from cte2 group by outputid
于 2010-06-10T10:31:45.463 に答える
17

http://groupconcat.codeplex.comから SQLCLR 集計をインストールします。

次に、次のようなコードを記述して、求めた結果を得ることができます。

CREATE TABLE foo
(
 id INT,
 name CHAR(1),
 Value CHAR(1)
);

INSERT  INTO dbo.foo
    (id, name, Value)
VALUES  (1, 'A', '4'),
        (1, 'B', '8'),
        (2, 'C', '9');

SELECT  id,
    dbo.GROUP_CONCAT(name + ':' + Value) AS [Column]
FROM    dbo.foo
GROUP BY id;
于 2016-03-19T03:40:12.453 に答える
13

SQL Server 2005 以降では、連結などを含む独自のカスタム集計関数を作成できます。リンクされた記事の下部にあるサンプルを参照してください。

于 2008-11-20T04:11:23.167 に答える
9

これは、Kevin Fairchild の投稿 (ちなみに非常に賢い) への単なる追加です。コメントとして追加したかったのですが、まだ十分なポイントがありません:)

作業中のビューにこのアイデアを使用していましたが、連結していたアイテムにスペースが含まれていました。そこで、スペースを区切り文字として使用しないようにコードを少し変更しました。

クールな回避策のケビンに再び感謝します!

CREATE TABLE #YourTable ( [ID] INT, [Name] CHAR(1), [Value] INT ) 

INSERT INTO #YourTable ([ID], [Name], [Value]) VALUES (1, 'A', 4) 
INSERT INTO #YourTable ([ID], [Name], [Value]) VALUES (1, 'B', 8) 
INSERT INTO #YourTable ([ID], [Name], [Value]) VALUES (2, 'C', 9) 

SELECT [ID], 
       REPLACE(REPLACE(REPLACE(
                          (SELECT [Name] + ':' + CAST([Value] AS VARCHAR(MAX)) as A 
                           FROM   #YourTable 
                           WHERE  ( ID = Results.ID ) 
                           FOR XML PATH (''))
                        , '</A><A>', ', ')
                ,'<A>','')
        ,'</A>','') AS NameValues 
FROM   #YourTable Results 
GROUP  BY ID 

DROP TABLE #YourTable 
于 2011-05-09T16:12:18.847 に答える
8

この種の質問はここで非常によく聞かれます。解決策は、基本的な要件に大きく依存します。

https://stackoverflow.com/search?q=sql+pivot

https://stackoverflow.com/search?q=sql+concatenate

通常、動的 SQL、ユーザー定義関数、またはカーソルを使用せずにこれを行う SQL のみの方法はありません。

于 2008-11-07T19:13:47.010 に答える
7

Cade 氏の発言に付け加えると、これは通常、フロントエンドの表示に関するものであり、そこで処理する必要があります。ファイル エクスポートやその他の "SQL のみ" のソリューションなど、100% SQL で何かを記述する方が簡単な場合があることはわかっていますが、ほとんどの場合、この連結はディスプレイ レイヤーで処理する必要があります。

于 2008-11-07T19:22:42.077 に答える
5

カーソルは必要ありません... while ループで十分です。

------------------------------
-- Setup
------------------------------

DECLARE @Source TABLE
(
  id int,
  Name varchar(30),
  Value int
)

DECLARE @Target TABLE
(
  id int,
  Result varchar(max) 
)


INSERT INTO @Source(id, Name, Value) SELECT 1, 'A', 4
INSERT INTO @Source(id, Name, Value) SELECT 1, 'B', 8
INSERT INTO @Source(id, Name, Value) SELECT 2, 'C', 9


------------------------------
-- Technique
------------------------------

INSERT INTO @Target (id)
SELECT id
FROM @Source
GROUP BY id

DECLARE @id int, @Result varchar(max)
SET @id = (SELECT MIN(id) FROM @Target)

WHILE @id is not null
BEGIN
  SET @Result = null

  SELECT @Result =
    CASE
      WHEN @Result is null
      THEN ''
      ELSE @Result + ', '
    END + s.Name + ':' + convert(varchar(30),s.Value)
  FROM @Source s
  WHERE id = @id

  UPDATE @Target
  SET Result = @Result
  WHERE id = @id

  SET @id = (SELECT MIN(id) FROM @Target WHERE @id < id)
END

SELECT *
FROM @Target
于 2008-11-07T19:29:26.230 に答える
0

ゴミのない別の例: ",TYPE).value('(./text())[1]','VARCHAR(MAX)')"

WITH t AS (
    SELECT 1 n, 1 g, 1 v
    UNION ALL 
    SELECT 2 n, 1 g, 2 v
    UNION ALL 
    SELECT 3 n, 2 g, 3 v
)
SELECT g
        , STUFF (
                (
                    SELECT ', ' + CAST(v AS VARCHAR(MAX))
                    FROM t sub_t
                    WHERE sub_t.g = main_t.g
                    FOR XML PATH('')
                )
                , 1, 2, ''
        ) cg
FROM t main_t
GROUP BY g

入出力は

*************************   ->  *********************
*   n   *   g   *   v   *       *   g   *   cg      *
*   -   *   -   *   -   *       *   -   *   -       *
*   1   *   1   *   1   *       *   1   *   1, 2    *
*   2   *   1   *   2   *       *   2   *   3       *
*   3   *   2   *   3   *       *********************
*************************   
于 2020-10-14T04:50:16.280 に答える