SQLクエリから返された差分行のすべての列値を1つの値に連結する方法は?これは一例です:
クエリは以下を返します:
FOO ------ RES1 RES2 RES3
今、私は次のような結果が欲しいです:
FOOCONCAT ----- 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
複数の値を持つ1つの列であると仮定すると、このアプローチはMS SQL Serverで機能します(他のシステムについて話すことはできません)。
declare @result varchar(max)
set @result = ''
select @result = @result + RES
from (query goes here)
Mysqlの方法:
select group_concat(somecolumn separator '') from sometable
Edit:バージョン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に置き換えます。
クエリによって返された列のすべてのレコードをT-SQLの1つのvarchar文字列に連結する方法は? で答えを見つけました
declare @s varchar(8000)
select @s = coalesce(@s + col, col) from tbl
これは解決するはずです
文字列の連結は、使用しているデータベースに依存します(質問でバージョンを言及しているため、ここで説明します)...
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 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;
SQL Server 2008 R2:
declare @ColumnNameList VARCHAR(MAX)
SELECT @ColumnNameList = COALESCE(@ColumnNameList +',' ,'') + ColumnName
FROM
<<table name>>
select @ColumnNameList
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 [〜#〜] を使用します。