80以上のスパース列と列セット列を含むテーブルがあります。これは簡単な例です。
DROP TABLE IF EXISTS #ColumnSet
GO
CREATE TABLE #ColumnSet
(
Id INT NOT NULL
, Value1 VARCHAR(100) SPARSE NULL
, Value2 VARCHAR(100) SPARSE NULL
, Value3 VARCHAR(100) SPARSE NULL
, Value4 VARCHAR(100) SPARSE NULL
, AllValues XML COLUMN_SET FOR ALL_SPARSE_COLUMNS
)
GO
INSERT INTO #ColumnSet
(Id, Value1, Value2, Value3, Value4)
VALUES
(1, 'POSITIVE', NULL, NULL, NULL),
(2, 'NEGATIVE', NULL, 'NEGATIVE', NULL),
(3, NULL, NULL, 'NEGATIVE', 'POSITIVE'),
(4, 'NEGATIVE', NULL, 'THIS IS NOT A POSITIVE RESULT', NULL)
GO
列セットをクエリして、いずれかの列の値がPOSITIVEである行を特定します。
列セットでvalue
メソッドを使用すると、すべての値が1つの文字列に連結され、LIKE
を使用できますが、値が別の文字列内にある結果は必要ありません。
SELECT
*
FROM
#ColumnSet
WHERE
AllValues.value('/', 'nvarchar(4000)') LIKE '%POSITIVE%'
上記を達成するために列セットをクエリする別の方法はありますか? APPLY
をnodes
メソッドと一緒に使用すると、同じ連結文字列出力が提供されますが、構文が正しくない可能性があります。
必要な出力:
id
1
3
これがXPathソリューションですが、どれほど効率的かはわかりません。
SELECT *
FROM #ColumnSet
WHERE AllValues.exist('//*[text() = "POSITIVE"]') = 1
これが別のxqueryソリューションです。
SELECT *, cs.AllValues.query('. [contains(., "POSITIVE")]')
FROM #ColumnSet AS cs
WHERE cs.AllValues.exist('. [contains(., "POSITIVE")]') = 1
サンプルデータを変更したため、上記は機能しません。
代わりにこれを行うことができます:
SELECT cs.*
FROM #ColumnSet AS cs
CROSS APPLY cs.AllValues.nodes('/*') AS x(c)
WHERE x.c.exist('text()[. = "POSITIVE"]') = 1;
しかし、それがミカエルの答えと大規模にどのように競合するかはわかりません。