4

ROW_NUMBER特定のインデックス(配列インデクサーなど)を持つシーケンスから特定のアイテムを選択できるように、cteに提供したいと思いarr[index]ます。もちろん、「シーケンス」はtable-valued-function(Split)からのテーブルです。

では、インデックスが利用できない場合、どうすればインデックスを作成できますか?これはクエリです:

DECLARE @string VARCHAR(100); 
SET @string='field1;field2;field3;field4;field5;field6;field7'; 
DECLARE @index INT; 
SET @index = 4; 

WITH cte 
     AS (SELECT item, 
                rn=Row_number() 
                     OVER( 
                       ORDER BY item) 
         FROM   dbo.Split(@string, ';')) 
SELECT TOP 1 item 
FROM   cte 
WHERE  rn = @index 

Row_number() OVER(ORDER BY item)アルファベット順に注文しますが、実際には(利用できない)インデックスで注文したいと思います。

この質問は、このそう質問に対する私の答えから生じたことに注意してください。

4

2 に答える 2

4

もちろん、各アイテムがリストのどこに表示されるかを追跡する必要があります。これを行う1つの方法は、分割関数にIDENTITY列を挿入させることです。あなたが参照する質問から私の答えを取る:

CREATE FUNCTION dbo.SplitStrings
(
    @List       NVARCHAR(MAX),
    @Delimiter  NVARCHAR(255)
)
RETURNS @t TABLE([Index] INT IDENTITY(1,1), Item NVARCHAR(255))
AS
BEGIN
    INSERT @t(Item) SELECT SUBSTRING(@List, Number, 
        CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number)
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
        FROM sys.all_objects) AS n(Number)
    WHERE Number <= CONVERT(INT, LEN(@List))
        AND SUBSTRING(@Delimiter + @List, Number, 1) = @Delimiter
    ORDER BY Number OPTION (MAXDOP 1);

    RETURN;
END
GO

DECLARE @x TABLE(i INT, string NVARCHAR(4000));

INSERT @x SELECT 1, N'field1;field2;field3;field4;field5;'
UNION ALL SELECT 2, N'x;y;6;r;3;2;w;'
UNION ALL SELECT 3, N'ttt;444;rrr;333;111;444;777;888;';

SELECT x.i, s1.Item
FROM @x AS x
CROSS APPLY dbo.SplitStrings(x.string, ';') AS s1
WHERE s1.[Index] = 4;

インラインの代替案。大規模では少しわかりやすいかもしれません

CREATE FUNCTION dbo.SplitStrings
(
    @List       NVARCHAR(MAX),
    @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
AS
    RETURN (SELECT [Index] = ROW_NUMBER() OVER (ORDER BY Number),
        Item FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(@List, Number, 
        CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number)))
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
        FROM sys.all_objects) AS n(Number)
    WHERE Number <= CONVERT(INT, LEN(@List))
        AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter
    ) AS y);
GO

もちろん、最終的にはスキーマを修正する必要があります。このリストの4番目の要素が重要なデータである場合は、個別に保存する必要があります。

于 2013-03-08T13:07:32.663 に答える
2

文字列の値が一意である場合はORDER BY charindex(';'+item+';', ';'+@string+';')OVER()句で使用できます。

DECLARE @string VARCHAR(100); 
SET @string='field1;field2;field3;field4;field5;field6;field7'; 
DECLARE @index INT; 
SET @index = 4; 

WITH cte 
     AS (SELECT item, 
                rn=Row_number() 
                     OVER( 
                       ORDER BY charindex(';'+item+';', ';'+@string+';')) 
         FROM   dbo.Split(@string, ';')) 
SELECT TOP 1 item 
FROM   cte 
WHERE  rn = @index 

charindex@string抽出されたそれぞれの位置を返すitemので、の位置rnに従って生成され@stringます。

SQLフィドル

于 2013-03-08T13:46:42.487 に答える