のある列があります。区切り文字としては、次のようになります。
_abc.efg.hij
_
これをCol1、Col2、およびCol3の3つの列に変換するクエリが必要です。これを行う最速の方法は何だと思います。これまでのところ、データベースの経験が限られているため、うまくうまくいくことができませんでした。私は関数を持っています:
_CREATE FUNCTION [dbo].[split](
@delimited NVARCHAR(MAX),
@delimiter NVARCHAR(100)
) RETURNS @t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
AS
BEGIN
DECLARE @xml XML
SET @xml = N'<t>' + REPLACE(@delimited,@delimiter,'</t><t>') + '</t>'
INSERT INTO @t(val)
SELECT r.value('.','varchar(MAX)') as item
FROM @xml.nodes('/t') as records(r)
RETURN
END
_
これは私が今それをやっている方法ですが、私はそれをはるかに速くすることができると私は信じています。また、文字列を分割するための大幅に優れた機能や枠外のアイデアにも開放的です。私はこれを実行していると信じていますdbo.split(Name, '.')
を3回実行すると、1回しか実行できません。
_SELECT
Col1 = (SELECT Val from dbo.split(Name, '.') WHERE Id = '1'),
Col2 = (SELECT Val from dbo.split(Name, '.') WHERE Id = '2'),
Col3 = (SELECT Val from dbo.split(Name, '.') WHERE Id = '3')
FROM Mains
_
どんな助けでも大歓迎です
の代わりに:
_SELECT
Col1 = (SELECT Val from dbo.split(Name, '.') WHERE Id = '1'),
Col2 = (SELECT Val from dbo.split(Name, '.') WHERE Id = '2'),
Col3 = (SELECT Val from dbo.split(Name, '.') WHERE Id = '3')
FROM Mains
_
使用する:
_SELECT
s.*
FROM Mains
CROSS APPLY (
SELECT
MAX(CASE WHEN Id = 1 THEN Val END) AS Col1,
MAX(CASE WHEN Id = 2 THEN Val END) AS Col2,
MAX(CASE WHEN Id = 3 THEN Val END) AS Col3
FROM dbo.split(Name,'.') s
) s
_
それでも、メインの行ごとに正確に1行が必要であるという考えです。そして、_CROSS APPLY
_内で集約関数を使用すると、まさにそれが可能になります。 CASEを使用すると、行ごとにsplit()
を呼び出すだけで済みます。
文字列の分割については、この辺りにたくさんの質問があり、SQL DBにはすでにstring_split()
関数が組み込まれています。
区切り文字はドットなので、これを行う非常に簡潔な方法は
SELECT Col1 = PARSENAME(name,3),
Col2 = PARSENAME(name,2),
Col3 = PARSENAME(name,1)
FROM Mains
上記は、PARSENAME
がドット区切りのSQL Serverオブジェクト名を解析するためのものであり、NULL
に収まらない場合にSYSNAME
を返すため、128文字を超えるコンポーネントパーツには依存しません。
パフォーマンステストはまだ行っていません。以下の方がパフォーマンスが良いと思います。
SELECT Col1 = LEFT(name, FirstDot - 1),
Col2 = SUBSTRING(name, FirstDot + 1, SecondDot - FirstDot - 1),
Col3 = SUBSTRING(name, 1 + SecondDot, 8000)
FROM Mains
CROSS APPLY (VALUES(CHARINDEX('.', name))) V1(FirstDot)
CROSS APPLY (VALUES(CHARINDEX('.', name, 1 + FirstDot))) V2(SecondDot)