MySQLのCONCATでGROUP_CONCATを使用する方法


117

MySQLに次のデータを含むテーブルがある場合:

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

次の形式にするにはどうすればよいですか?

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


使う必要があると思いますGROUP_CONCAT。しかし、それがどのように機能するかはわかりません。

回答:


160
select id, group_concat(`Name` separator ',') as `ColumnName`
from
(
  select 
    id, 
    concat(`Name`, ':', group_concat(`Value` separator ',')) as `Name`
  from mytbl
  group by 
    id, 
    `Name`
) tbl
group by id;

あなたはそれがここに実装されているのを見ることができます:Sql Fiddle Demo。まさにあなたが必要とするもの。

2つのステップで分割を更新します。最初に、unique [Name、id]に対してすべての値(カンマ区切り)を持つテーブルを取得します。次に、取得したテーブルから、すべての名前と値を各一意のIDに対する単一の値として取得します。これについては、ここで説明します。SQLFiddleデモ(2つの結果セットがあるため、下にスクロールします)

編集質問を読んで間違いがありました、私はIDでグループ化していました。ただし、2つのgroup_contactsが必要です(値を名前とIDでグループ化して連結し、次にIDで連結します)。以前の答えは

select 
id,group_concat(concat(`name`,':',`value`) separator ',')
as Result from mytbl group by id

あなたはそれがここに実装されているのを見ることができます:SQL Fiddle Demo


これはBiswaが要求したものを与えません。
eisberg 2012年

3
1種類のセパレーターのみを使用することは不利になる可能性があることを人々に警告することが重要だと思います。「名前」の区切り文字をセミコロン(;)にすることをお勧めします。値の区切り文字はコンマ(、)のままにすることができます
Fandi Susanto '28

4
またGROUP_CONCAT、出力が暗黙的にに切り捨てられる可能性があることにも注意してくださいgroup_concat_max_lenSET group_concat_max_len=...は役立ちますが、とにかく返される(バイト?)の長さが未満であることを確認することをお勧めしますgroup_concat_max_len
tuomassalo 16

2
group_concatが単一のNULL値を検出すると、それを含んでいた行全体が省略されることにも注意してください。私はここの2番目の警告これを回避します
MatrixManAtYrService 2018

1
回答で与えられたSQL Fiddleリンクで問題に直面している場合。作業フィドルはこちら:sqlfiddle.com
#!9

21

試してください:

CREATE TABLE test (
  ID INTEGER,
  NAME VARCHAR (50),
  VALUE INTEGER
);

INSERT INTO test VALUES (1, 'A', 4);
INSERT INTO test VALUES (1, 'A', 5);
INSERT INTO test VALUES (1, 'B', 8);
INSERT INTO test VALUES (2, 'C', 9);

SELECT ID, GROUP_CONCAT(NAME ORDER BY NAME ASC SEPARATOR ',')
FROM (
  SELECT ID, CONCAT(NAME, ':', GROUP_CONCAT(VALUE ORDER BY VALUE ASC SEPARATOR ',')) AS NAME
  FROM test
  GROUP BY ID, NAME
) AS A
GROUP BY ID;

SQLフィドル:http ://sqlfiddle.com/#!2/b5abe/9/ 0


2
はいアイズバーグ+1。あなたの答えはかなり正確で早いです。初めての回答で間違いをしました
Sami

9
SELECT ID, GROUP_CONCAT(CONCAT_WS(':', NAME, VALUE) SEPARATOR ',') AS Result 
FROM test GROUP BY ID

7
あなたの答えにいくつかの説明を追加できるといいですね。これは、これと将来の答えを改善するための提案です。ありがとう!
ルイス・クルーズ

5

まず、一意ではないIDを使用する理由はわかりませんが、別のテーブルに接続するIDだと思います。第2に、サーバーに負荷をかけるサブクエリは必要ありません。このように、1つのクエリでこれを行います

SELECT id,GROUP_CONCAT(name, ':', value SEPARATOR "|") FROM sample GROUP BY id

高速で正しい結果が得られ、その区切り記号「|」で結果を分割できます。文字列内でそれを見つけることは不可能であるため、私は常にこのセパレータを使用します。そのため、それはユニークです。2つのAがあっても問題はありません。値のみを識別します。または、文字が付いた列をもう1つ持つこともできます。このような :

SELECT id,GROUP_CONCAT(DISTINCT(name)), GROUP_CONCAT(value SEPARATOR "|") FROM sample GROUP BY name

2
 SELECT id, GROUP_CONCAT(CONCAT_WS(':', Name, CAST(Value AS CHAR(7))) SEPARATOR ',') AS result 
    FROM test GROUP BY id

キャストまたは変換を使用する必要があります。それ以外の場合はBLOBが返されます

結果は

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

あなたはPythonやJavaなどのプログラムでもう一度結果を処理する必要があります


0

IF OBJECT_ID('master..test') is not null Drop table test

CREATE TABLE test (ID INTEGER, NAME VARCHAR (50), VALUE INTEGER );
INSERT INTO test VALUES (1, 'A', 4);
INSERT INTO test VALUES (1, 'A', 5);
INSERT INTO test VALUES (1, 'B', 8);
INSERT INTO test VALUES (2, 'C', 9);

select distinct NAME , LIST = Replace(Replace(Stuff((select ',', +Value from test where name = _a.name for xml path('')), 1,1,''),'<Value>', ''),'</Value>','') from test _a order by 1 desc

私のテーブル名はtestで、連結のためにFor XML Path( '')構文を使用しています。stuff関数は、文字列を別の文字列に挿入します。最初の文字列の開始位置にある指定された長さの文字を削除し、2番目の文字列を最初の文字列の開始位置に挿入します。

STUFF関数は次のようになります。STUFF(character_expression、start、length、character_expression)

character_expression文字データの式です。character_expressionには、定数、変数、または文字またはバイナリデータの列を指定できます。

start削除と挿入を開始する場所を指定する整数値です。startまたはlengthが負の場合、null文字列が返されます。startが最初のcharacter_expressionより長い場合、null文字列が返されます。startはbigint型にすることができます。

length削除する文字数を指定する整数です。長さが最初のcharacter_expressionより長い場合、削除は最後のcharacter_expressionの最後の文字まで発生します。lengthは、bigintタイプにすることができます。


0

SELECT id、Group_concat(column)FROM(SELECT id、Concat(name、 ':'、Group_concat(value))AS column FROM mytbl GROUP BY id、name)tbl GROUP BY id;

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.