web-dev-qa-db-ja.com

カンマ区切りの文字列フィールドをSQLクエリに分割/分解

フィールドid_list='1234,23,56,576,1231,567,122,87876,57553,1216'があります

それを使用して、このフィールドを検索しますIN

SELECT * 
FROM table1
WHERE id IN (id_list)
  • idinteger

  • id_listvarchar/textです

しかし、この方法ではこれは機能しないので、何らかの方法でid_listを選択クエリに分割する必要があります。

ここではどのソリューションを使用する必要がありますか? T-SQL Sybase ASA 9データベース(SQL Anywhere)を使用しています。しかし、この方法ではこれは機能しないので、何らかの方法でid_listを選択クエリに分割する必要があります。

これを私が見る方法は、whileループスルーを使用して独自の関数を作成し、各要素を区切り文字による位置検索に基づいて抽出し、関数が結果として返す要素を一時テーブルに挿入することです。


Sebastian Meineの回答と彼の解決策へのコメント:

Sybase SQL Anywhere 9

  • sa_split_listシステムプロシージャはここに存在しないため、機能しません

  • CASTは素晴らしい

Sybase SQL Anywhere 12

  • sa_split_listシステムプロシージャが存在し、正常に動作しています

  • CASTは素晴らしい

Sybase SQL Anywhere 9の場合は、sa_split_listシステムプロシージャを置き換えました。

CREATE PROCEDURE str_split_list(in str long varchar, in delim char(10) default ',')
RESULT(
  line_num integer,
  row_value long varchar)
BEGIN
  DECLARE str2 long varchar;
  DECLARE position integer;

   CREATE TABLE #str_split_list (
   line_num integer DEFAULT AUTOINCREMENT,
   row_value long varchar null,
   primary key(line_num));

   SET str = TRIM(str)+delim;
   SET position = CHARINDEX(delim, str);

   separaterows:
   WHILE position > 0 loop
       SET str2 = TRIM(LEFT(str, position - 1));
       INSERT INTO #str_split_list (row_value)
       VALUES (str2);
       SET str = RIGHT(str, LENGTH(str) - position);
       SET position = CHARINDEX(delim, str);
    end loop separaterows;

   select * from #str_split_list order by line_num asc;

END

Sa_split_listと同じ方法で実行します。

select * from str_split_list('1234,23,56,576,1231,567,122,87876,57553,1216')
5
BlueMark

実際にテストするsybaseシステムはありませんが、 http://dcx.sybase.com/1200/en/dbreference/sa-split-list-sysproc.html によると、ソリューションはうまくいくはずです:

SELECT * 
  FROM table AS T
  JOIN sa_split_list('1234,23,56,576,1231,567,122,87876,57553,1216') AS L
    ON T.id = L.row_value;

Id_listが実際に別のテーブル(list_tableなど)に格納されている場合は、CROSS APPLY演算子も使用する必要があります( http://dcx.sybase.com/1101/en/dbusage_en11/apply-joins- joinsasp.html ):

SELECT *
  FROM list_table AS LT
 CROSS APPLY sa_split_list(LT.id_list) L
  JOIN table T
    ON T.id = L.row_value
   AND <optional: some other condition that ties rows in list_table to rows in table, like a group membership or location>

分割された部分は自動的にid列のデータ型にキャストされるため、これはすべてこれらのリストの一部である必要があります。それが当てはまらない場合は、このより簡単な、しかし遅いテクニックを使うことができます:

SELECT *
  FROM table
 WHERE ','+@id_list+',' LIKE '%,'+CAST(id AS VARCHAR(20))+',%'

最後の例では、idリストが変数@id_listにあると想定しています。別のテーブルにある場合は、上記と同じCROSS APPLYテクニックを使用できます。追加のカンマは、最初または最後のエントリが一致できることを確認します。

8
Sebastian Meine