4

SQLクエリのヘルプが必要です。値がコンマ区切りの値として格納されている列があります。

列の各値内で3番目に区切られた項目を見つけるクエリを作成する必要があります。

これをSelectステートメントで行うことは可能ですか?例:ColumnValue:josh,Reg01,False,a0-t0,22/09/2010

Falseしたがって、上記の文字列から3番目の値(つまり)を取得する必要があります。

4

4 に答える 4

6

はい。

あなたのひもはどこ@sにありますか...

select 
    SUBSTRING (@s,
    CHARINDEX(',',@s,CHARINDEX(',',@s)+1)+1,
    CHARINDEX(',',@s,CHARINDEX(',',@s,CHARINDEX(',',@s)+1)+1)
          -CHARINDEX(',',@s,CHARINDEX(',',@s)+1)-1)

またはより一般的に...

;with cte as 
(
    select 1 as Item, 1 as Start, CHARINDEX(',',@s, 1) as Split
    union all
    select cte.Item+1, cte.Split+1, nullif(CHARINDEX(',',@s, cte.Split+1),0) as Split
    from cte
    where cte.Split<>0  
)   
select SUBSTRING(@s, start,isnull(split,len(@s)+1)-start) 
from cte 
where Item = 3

データを適切に保存します:)

于 2012-09-05T09:22:49.457 に答える
4

これを試してください(SQL Server 2005以降を想定)

DECLARE @t TABLE(ColumnValue VARCHAR(50))
INSERT INTO @t(ColumnValue) SELECT 'josh,Reg01,False,a0-t0,22/09/2010'
INSERT INTO @t(ColumnValue) SELECT 'mango,apple,bannana,grapes'
INSERT INTO @t(ColumnValue) SELECT 'stackoverflow'

SELECT ThirdValue = splitdata
FROM(
        SELECT 
            Rn = ROW_NUMBER() OVER(PARTITION BY ColumnValue ORDER BY (SELECT 1))
            ,X.ColumnValue
            ,Y.splitdata 
        FROM
         (
            SELECT *,
            CAST('<X>'+REPLACE(F.ColumnValue,',','</X><X>')+'</X>' AS XML) AS xmlfilter FROM @t F
         )X
         CROSS APPLY
         ( 
            SELECT fdata.D.value('.','varchar(50)') AS splitdata 
            FROM X.xmlfilter.nodes('X') as fdata(D)
         ) Y
    )X WHERE X.Rn = 3

//結果

サードバリュー

False
bannana

また、使用している SQL Server のバージョンが質問から明確ではありません。SQL SERVER 2000 を使用している場合は、以下の方法を使用できます。

ステップ 1: 数表を作成する

CREATE TABLE dbo.Numbers
(
   N INT NOT NULL PRIMARY KEY
);
GO

DECLARE @rows AS INT;
SET @rows = 1;

INSERT INTO dbo.Numbers VALUES(1);
WHILE(@rows <= 10000)
BEGIN
   INSERT INTO dbo.Numbers SELECT N + @rows FROM dbo.Numbers;
   SET @rows = @rows * 2;
END 

ステップ 2: 以下のクエリを適用する

DECLARE @t TABLE(ColumnValue VARCHAR(50))
INSERT INTO @t(ColumnValue) SELECT 'josh,Reg01,False,a0-t0,22/09/2010'
INSERT INTO @t(ColumnValue) SELECT 'mango,apple,bannana,grapes'
INSERT INTO @t(ColumnValue) SELECT 'stackoverflow'

--Declare a table variable to put the identity column and store the indermediate results
DECLARE @tempT TABLE(Id INT IDENTITY,ColumnValue VARCHAR(50),SplitData VARCHAR(50))

-- Insert the records into the table variable
INSERT INTO @tempT
SELECT  
    ColumnValue
    ,SUBSTRING(ColumnValue, Numbers.N,CHARINDEX(',', ColumnValue + ',', Numbers.N) - Numbers.N) AS splitdata 
FROM @t 
JOIN Numbers ON Numbers.N <= DATALENGTH(ColumnValue) + 1  
AND SUBSTRING(',' + ColumnValue, Numbers.N, 1) = ','  

--Project the filtered records

SELECT ThirdValue = X.splitdata
FROM
--The co-related subquery does the ROW_NUMBER() OVER(PARTITION BY ColumnValue)
(SELECT 
  Rn = (SELECT COUNT(*) 
        FROM @tempT t2 
        WHERE t2.ColumnValue=t1.ColumnValue 
        AND t2.Id<=t1.Id)
 ,t1.ColumnValue
 ,t1.splitdata
FROM @tempT t1)X
WHERE X.Rn =3

- 結果

サードバリュー

False
bannana

また、数値テーブルに Master..spt_Values を使用できます

DECLARE @t TABLE(ColumnValue VARCHAR(50))
INSERT INTO @t(ColumnValue) SELECT 'josh,Reg01,False,a0-t0,22/09/2010'
INSERT INTO @t(ColumnValue) SELECT 'mango,apple,bannana,grapes'
INSERT INTO @t(ColumnValue) SELECT 'stackoverflow'

--Declare a table variable to put the identity column and store the indermediate results
DECLARE @tempT TABLE(Id INT IDENTITY,ColumnValue VARCHAR(50),SplitData VARCHAR(50))

-- Insert the records into the table variable
INSERT INTO @tempT
SELECT  
    ColumnValue
    ,SUBSTRING(ColumnValue, Number ,CHARINDEX(',', ColumnValue + ',', Number ) - Number) AS splitdata 
FROM @t 
JOIN master..spt_values ON Number <= DATALENGTH(ColumnValue) + 1  AND type='P'
AND SUBSTRING(',' + ColumnValue, Number , 1) = ','  

--Project the filtered records
SELECT ThirdValue = X.splitdata
FROM
--The co-related subquery does the ROW_NUMBER() OVER(PARTITION BY ColumnValue)
(SELECT 
  Rn = (SELECT COUNT(*) 
        FROM @tempT t2 
        WHERE t2.ColumnValue=t1.ColumnValue 
        AND t2.Id<=t1.Id)
 ,t1.ColumnValue
 ,t1.splitdata
FROM @tempT t1)X
WHERE X.Rn =3

これについては、

1)システム テーブル table master..spt_values の目的とその値の意味は何ですか?

2) master..spt_values を使用して列を分割する理由 (および方法) は?

于 2012-09-05T10:14:24.510 に答える
2

残念ながらSQLには存在しない String.Split(',')(2) のようなものが本当に必要ですが、これは役立つかもしれません

于 2012-09-05T09:25:18.240 に答える
1

このソリューションと他のソリューションを使用していくつかのテストを行うことができますが、そのような状況で XML を使用すると、ほとんどの場合、最高のパフォーマンスが得られ、コーディングが少なくて済むと思います。

DECLARE @InPutCSV NVARCHAR(2000)= 'josh,Reg01,False,a0-t0,22/09/2010'
DECLARE @ValueIndexToGet INT=3
DECLARE @XML XML =  CAST ('<d>' + REPLACE(@InPutCSV, ',', '</d><d>') + '</d>' AS XML);

WITH CTE(RecordNumber,Value) AS
(
     SELECT  ROW_NUMBER() OVER(ORDER BY T.v.value('.', 'NVARCHAR(100)') DESC) AS RecordNumber
             ,T.v.value('.', 'NVARCHAR(100)') AS Value
     FROM @XML.nodes('/d') AS T(v)
)
SELECT Value
FROM CTE WHERE RecordNumber=@ValueIndexToGet

100000個の値を持つCSV文字列から値を取得するのに1秒かかることを確認できます。

于 2012-09-05T12:43:39.957 に答える