SQLクエリから返された異なる行のすべての列の値を1つの値に連結する方法は? これは例です:
クエリは次を返します。
フー ------ RES1 RES2 RES3
今、私は次のような結果を得たいと思っています:
フーコンキャット ----- RES1RES2RES3
SQLでこれを行う方法はありますか?
SQLクエリから返された異なる行のすべての列の値を1つの値に連結する方法は? これは例です:
クエリは次を返します。
フー ------ RES1 RES2 RES3
今、私は次のような結果を得たいと思っています:
フーコンキャット ----- RES1RES2RES3
SQLでこれを行う方法はありますか?
でSQL Server
:
SELECT col1 AS [text()]
FROM foo
FOR XML PATH ('')
でMySQL
:
SELECT GROUP_CONCAT(col1 SEPARATOR '')
FROM foo
でPostgreSQL
:
SELECT array_to_string
(
ARRAY
(
SELECT col1
FROM foo
), ''
)
でOracle
:
SELECT *
FROM (
SELECT col1, ROW_NUMBER() OVER(ORDER BY 1) AS rn
FROM foo
MODEL
DIMENSION BY
(rn)
MEASURES
(col1, col1 AS group_concat, 0 AS mark)
RULES UPDATE (
group_concat[rn > 1] = group_concat[CV() - 1] || col1[CV()],
mark[ANY] = PRESENTV(mark[CV() + 1], 0, 1)
)
)
WHERE mark = 1
mysql の方法:
select group_concat(somecolumn separator '') from sometable
複数の値を持つ 1 つの列であると仮定すると、このアプローチは MS SQL Server で機能します (他のシステムについては言えません)。
declare @result varchar(max)
set @result = ''
select @result = @result + RES
from (query goes here)
編集:バージョン 8.4.0 以降、CUBRID はMySQL と90% の互換性を提供します。したがって、MySQL と同様の構文を持つGROUP_CONCATをサポートします。
CREATE TABLE t(i int);
INSERT INTO t VALUES (4),(2),(3),(6),(1),(5);
SELECT GROUP_CONCAT(i*2+1 ORDER BY 1 SEPARATOR '') FROM t;
group_concat(i*2+1 order by 1 separator '')
======================
'35791113'
かなり強力ですね。以下は、CUBRID でネイティブにサポートされている代替ソリューションです。
SELECT MAX(SYS_CONNECT_BY_PATH(s_name, '')) AS conc_s_name
FROM (
SELECT ROWNUM AS r, s_name FROM code
) AS res
START WITH r = 1
CONNECT BY PRIOR r = r - 1;
興味深いことに、CUBRID で異なる行の列の値を連結するこの方法は、@devio が提供する Oracle の方法とほとんど同じです。ただし、CUBRID では少し簡単に見えます。
これがあなたが探している答えです。解決策は CONNECT BY 操作にあると感じていましたが、以前は SYS_CONNECT_BY_PATH 疑似列を使用したことがありませんでした (ノードへのフルパスをツリーで表示し、ノード名を「/」で区切ります)。以前の「foo」値のセットは、列「myKey」でグループ化されたテーブル内の複数の行であると仮定します。
myKey foo
-------- ----------
group 1 apple
group 1 orange
group 1 pear
group 2 ape
group 2 bear
group 2 kitten
データをツリー スキーマであるかのように扱い、各グループの値が分岐を下るノードを表していると見なすことができます。その場合、次のようにします。
SELECT myKey
, SUBSTR(MAX(REPLACE(SYS_CONNECT_BY_PATH(foo, '/')
,'/'
,' '
)
)
,2
) FooConcat
FROM ( SELECT MyKey
, Foo
, row_number() OVER (Partition by myKey order by myKey) NodeDepth
FROM MyTable
)
START WITH NodeDepth = 1
CONNECT BY PRIOR myKey = myKey
AND PRIOR NodeDepth = NodeDepth -1
GROUP BY myKey
;
もちろん、連結された値の順序はランダムです。テーブルに、昇順で連続した順序付けフィールドとして使用できる別の列 (「バー」) がある場合は、サブクエリ (ツリーに想像上の深さを設定するためだけに存在する) を省略して、テーブルを直接使用できます。 NodeDepth を bar に置き換えます。
文字列の連結は、使用しているデータベースによって異なります(質問でどのバージョンについて言及していないので、ここに行きます)...
OracleおよびDB2では、関数を使用できますCONCAT
...CONCAT(string, string)
SQL Server では「+」演算子を使用できます...string1 + string2 + string3
MySQLではCONCAT(string, string... n_string)
最後にPostgreSQLではTEXTCAT(string, string)
...
...これは、机の上に置いてあるこの小さなクールな本から得たもので、O'Reilly の SQL Pocket Guide を読んでみてください!
:)
select cast(res1 as varchar)+cast(res2 as varchar)+cast(res3 as varchar) as fooconcat from foo
列がすでに文字列である場合、キャストは必要ありません。次のようにするだけです。
select res1 + res2 + res3 as fooconcat from foo
複数の行からのデータには、PIVOTを使用します。
あなたが探しているものではないかもしれませんが、私は過去に次のような構造で幸運に恵まれました:
SELECT MAX(DECODE(fookey, 1, foo, NULL))
|| MAX(DECODE(fookey, 2, foo, NULL))
|| MAX(DECODE(fookey, 3, foo, NULL))
|| MAX(DECODE(fookey, 4, foo, NULL))
, groupingvalue
FROM mytable
GROUP BY groupingvalue;
これはプラットフォームに依存せず、foo の値が任意ではあるが限られた数であり、それらが他のキー値に基づいている場合にうまく機能します。たとえば、請求書のテーブルがあり、請求書のすべてのライン タイムを 1 行に連結して表示したい場合、上限は 5 ライン アイテムで、次のようになります。
SELECT MAX(DECODE(lineno, 1, foo, NULL))
|| ', '
|| MAX(DECODE(lineno, 2, foo, NULL))
|| ', '
|| MAX(DECODE(lineno, 3, foo, NULL))
|| ', '
|| MAX(DECODE(lineno, 4, foo, NULL))
|| ', '
|| MAX(DECODE(lineno, 5, foo, NULL))
, invoiceid
FROM lineitem
GROUP BY invoiceid;
[テーブル] から [MyCol] として ([col1] +','+[col2]+','+ [col3]+','+[col4]) を選択します。