2022年5月22日日曜日

(PC) 文字列を1文字づつ分割してテーブル化する方法

今回の記事では、SQL-Serverでもって、「1001101011」等の文字列を1文字づつ分割してテーブルに格納する方法を記載いたします。

どういう時に使うか?

たとえば、工場等で途方もなく多数の設備(しかも増減する)の状態(正常・異常)をデータ化する場合、一つの方法として、多数の状態フラグを文字列として格納したとします。

データ量の削減のため、区切り文字も無いとします。

区切り文字も無い場合に、その文字を区切りたい...こんな場合は、1文字づつ分割してテーブル化すると良いでしょう。

まずは、連番だけのテーブルを作るのが味噌です。

この連番だけのテーブルさえあれば、パフォーマンスで難があるループ処理使用を一切せず、一文でテーブル用のレコードが生成出来るので、色々な場面で応用が効きます。




--1文字づつテーブルに分割したいデータ
DECLARE @IN_VALUE NVARCHAR(255) = N'1001101011';

-- --------------------------
--準備
-- --------------------------
--連番の元を生成する(1~255の連番テーブル)
WITH CTE000 AS (
    SELECT 1 AS SEQ
	UNION ALL
	SELECT SEQ + 1
	  FROM CTE000
	 WHERE SEQ < 255
)
SELECT SEQ
  INTO #SEQ --ワークテーブルに格納し再利用可能にしておく
  FROM CTE000
OPTION (MAXRECURSION 255); --これやらないと100個分でエラーになるのだった

-- --------------------------
-- 実行
-- --------------------------
SELECT T.SEQ
      ,W.DAT
  FROM #SEQ AS T --連番の素が主語
       CROSS APPLY (SELECT SUBSTRING(@IN_VALUE,T.SEQ,1) AS DAT) AS W 
 WHERE T.SEQ <= LEN(@IN_VALUE); --入力データの長さ分だけ




結果は以下のスクリーンショットのようになります。

区切り文字があれば、XML型を使って区切る方がシンプルかもですが、区切り文字が無いと逆に処理が分かりにくくなるのが悩みどころです。

SQL-Serverは、とにかくWHILE @@FETCH_STATUS = 0 BEGIN ~ END; 等のループ処理をしてしまうと急激なパフォーマンス悪化が出てしまうので、ループは最後の手段ですね...