2017-04-02 4 views
0

SQL Server上でスラッシュで展開された各文字列の日付を返したいとします。SQL Serverの一部の列で値が返されたときの戻り値

私のデータベーステーブル:

id | date  | col1  | col2  | col3 | col4 
---+------------+-------------+-----------+-------+------------ 
1 | 2017-04-02 | /txt1/txt2 |   |  | 
2 | 2017-04-03 |    | /txt1/txt4|  | 
3 | 2017-04-04 |    |/txt2/txt3 |  | 
4 | 2017-04-05 |    |/txt4  |  |/txt5/txt6 

結果が欲しかった:

2017-04-02 txt1 
2017-04-02 txt2 
2017-04-03 txt1 
2017-04-03 txt4 
2017-04-04 txt2 
2017-04-04 txt3 
2017-04-05 txt4 
2017-04-05 txt5 
2017-04-05 txt6 

ありがとう ピエール

+2

では、なぜあなたはこれまでにしようとしているものを私たちと共有しませんか? –

+0

を読む[データベース列に区切られたリストを格納するのは本当に悪いですか?](http://stackoverflow.com/questions/3653462/is-storing-a-delimited-list-in-a-database-column-really-この質問への答えは** Absolutly yes!** –

+0

@ZoharPeled OPはデータベースの設計に責任を負いませんが、それは事実です。 –

答えて

1

あなたが最初に必要になります(SQL Serverの2016年から入手可能)STRING_SPLIT() functionを使用することはできませんと仮定すると、 varchar列をトークン化する関数。ウェブには何百ものものがありますが、私はそれをあなたに任せていますが、最も適切でよくテストされたものを選ぶべきです。デモで

CREATE FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
     IF @end = 0 
      SET @end = LEN(@string) + 1 

     INSERT INTO @output (splitdata) 
     VALUES(SUBSTRING(@string, @start, @end - @start)) 
     SET @start = @end + 1 
     SET @end = CHARINDEX(@delimiter, @string, @start) 

    END 
    RETURN 
END 

select t.date, x.splitdata 
from test t 
cross apply dbo.fnSplitString(
    coalesce(col1, '') + coalesce(col2, '') 
    + coalesce(col3, '') + coalesce(col4, '') 
, '/') x 
where coalesce(x.splitdata, '') <> '' 

rextester demo

split関数を適用する。なお、I:私はあなたのサンプルのために働く、thisで行く私の例えば

date列の代わりにId列を使用しました。

+0

Aaron Bertrand [適切な方法で文字列を分割する]または[次善の方法](https://sqlperformance.com/2012/07/t-sql-queries/split-strings) –

+0

偉大な参照@ZoharPeled。 –

+0

@GiorgosAltanis努力の価値があります。パフォーマンスの向上に驚くかもしれません。 –

0

Zohar Peledがリンクしているので、誰もが良い分割/解析機能を持っているはずです。

UDFを使用できない(または使用したくない)場合は、別のオプションを選択します。

Select A.Date 
     ,C.RetVal 
From YourTable A 
Cross Apply (values (col1),(col2),(col3),(col4)) B (Value) 
Cross Apply (
       Select RetSeq = Row_Number() over (Order By (Select null)) 
         ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
       From (Select x = Cast('<x>' + replace((Select replace(B.Value,'/','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
       Cross Apply x.nodes('x') AS B(i) 
      ) C 
Where C.RetVal is not null 

戻り

Date  RetVal 
2017-04-02 txt1 
2017-04-02 txt2 
2017-04-03 txt1 
2017-04-03 txt4 
... 
関連する問題