0

次の形式のテーブルがあります(MS SQL Server 2008を使用しています)。

car_id | trace
1        1300275738;57.72588;11.84981;0.00026388888888888886;1300275793;57.72596;11.8529;0.001055...

トレース値は、デリミネーターとしてセミコロンを使用したcsv文字列です。トレース文字列の値は、次のように4つと4つにグループ化されます(改行がない場合を除く)。

1300275738;57.72588;11.84981;0.00026388888888888886;
1300275793;57.72596;11.8529;0.0010555555555555555;
1300275785;57.72645;11.85242;0.007416666666666665;
1300275780;57.72645;11.85242;0.0010138888888888888;

私がやりたいのは、4つのグループの最初の値に基づいてトレース文字列をソートする挿入時にトリガーを作成することです。したがって、上記の結果は次のようになります

1300275738;57.72588;11.84981;0.00026388888888888886;1300275780;57.72645;11.85242;0.0010138888888888888;1300275785;57.72645;11.85242;0.007416666666666665;1300275793;57.72596;11.8529;0.0010555555555555555;

私がやろうとしたことは、次のように一時テーブルの値を別々の行に分割することです。

USE tempdb
GO

checkpoint
dbcc dropcleanbuffers
dbcc freeproccache
GO

--declare a variable and populate it with a comma separated string
DECLARE @SQLString VARCHAR(MAX)
SET @SQLString = (SELECT trace FROM mypev_trips.dbo.trips)

--append a comma to the string to get correct results with empty strings or strings with a single value (no commas)
SET @SQLString = @SQLString + ';';

DECLARE @X XML
SET @X = CAST('<A>' + REPLACE(@SQLString, ';', '</A><A>') + '</A>' AS XML)

SELECT t.value('.', 'nvarchar(20)')
FROM @x.nodes('/A') as x(t)

これにより、次の結果が得られます。

(No column name)
1300275738
57.72588
11.84981
0.000263888888888888
1300275780
57.72645
11.85242
0.001013888888888888
.
.

一時テーブルを、4つの各グループの最初の値でソートされたコンマ区切りの文字列に戻す方法を知っている人はいますか?

4

2 に答える 2

0
;WITH cte(car_Id, traceXML) AS
 (
  SELECT car_Id, CAST('<A>' + REPLACE(trace, ';', '</A><A>') + '</A>' AS XML)
  FROM dbo.cars
  ), cte2 AS
 (
  SELECT car_Id, trace, NTILE(4) OVER(ORDER BY (SELECT 1)) AS grId  
  FROM cte
  CROSS APPLY (SELECT Tbl.Col.value('.', 'nvarchar(250)') AS trace 
               FROM traceXML.nodes('/A') Tbl(Col)) AS List
  ), cte3 AS
 (
  SELECT DISTINCT a.car_Id,(
  SELECT ISNULL(b.trace, '') + ';' 
  FROM cte2 b 
  WHERE b.grId = a.grId
  FOR XML PATH('')) AS trace
  FROM cte2 a
  )
  SELECT DISTINCT a.car_Id,(
  SELECT ISNULL(b.trace, '')
  FROM cte3 b
  WHERE b.car_Id = a.car_Id
  FOR XML PATH('')) AS trace
  FROM cte3 a

SQLFiddleのデモ

于 2012-12-03T23:45:06.320 に答える
0

最終的に2つの関数と1つのトリガーを使用しました。

まず、トレース文字列を行に分割する関数

CREATE FUNCTION dbo.Split(@String varchar(MAX))       
returns @temptable TABLE (items varchar(MAX)) 
as       
begin       
    declare @idx int       
    declare @idx2 int
    declare @idx3 int
    declare @idx4 int
    declare @slice varchar(8000)

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx != 0       
    begin       
        set @idx = charindex(';',@String)       
        if @idx!=0       
            set @slice = left(@String,@idx)       
        else       
            set @slice = @String       

        set @String = right(@String,len(@String) - @idx)
        set @idx2 = charindex(';',@String);

        if @idx2!=0       
            set @slice = @slice + left(@String,@idx2)

        set @String = right(@String,len(@String) - @idx2)
        set @idx3 = charindex(';',@String);

        if @idx3!=0       
            set @slice = @slice + left(@String,@idx3)

        set @String = right(@String,len(@String) - @idx3)
        set @idx4 = charindex(';',@String);

        if @idx4 !=0       
            set @slice = @slice + left(@String,@idx4)
        else
            set @slice = @slice + @String

        if(len(@slice)>0)
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx4) 
        if len(@String) = 0 break
        if @idx4 = 0 break   
    end
return      
end

次に、一時テーブルの行を並べ替えてマージする関数

CREATE FUNCTION dbo.SortCSV(@String varchar(MAX))       
returns varchar(MAX)
as
begin
    declare @csv varchar(MAX)
    select @csv = coalesce(@csv,'') + items
    from dbo.Split(@String)
    order by items asc
return @csv
end

そしてついに私はこのようなトリガーを作成しました

CREATE TRIGGER dbo.SortTrace 
   ON  dbo.trips 
   INSTEAD OF INSERT
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @trace varchar(MAX);
    DECLARE @sorted_trace varchar(MAX);

    SELECT @trace = trace FROM inserted;
    SELECT @sorted_trace = dbo.SortCSV(@trace);

    insert into dbo.trips (
        car_id, start, stop, distance, created_at, updated_at, trace, energy, delta_soc, private_trip, journal_comment
    ) select
        car_id, start, stop, distance, created_at, updated_at, @sorted_trace, energy, delta_soc, private_trip, journal_comment
    from
        inserted
END
GO
于 2012-12-04T07:18:14.950 に答える