2017-06-05 9 views
0

1対多の関係を持つ2つのテーブルがあります。 クエリを実行した後、私は結果表ました:クエリ内の行数から1行を作成する

+-------+------------------+-----------+-------+--------+ 
| index |  date  | sub_index | angle | length | 
+-------+------------------+-----------+-------+--------+ 
| 681 | 19/10/2016 15:49 |   1 | 30 | 333 | 
| 681 | 19/10/2016 15:49 |   1 | 60 | 666 | 
| 682 | 19/10/2016 15:52 |   2 |  0 |  44 | 
| 682 | 19/10/2016 15:52 |   2 | 45 |  77 | 
| 682 | 19/10/2016 15:52 |   2 | 90 |  67 | 
+-------+------------------+-----------+-------+--------+ 

をしかし、ユーザーは平坦に情報を求めました。次のように:

+-------+------------------+-----------+--------+---------+--------+---------+--------+---------+ 
| index |  date  | sub_index | angle1 | length1 | angle2 | length2 | angle3 | length3 | 
+-------+------------------+-----------+--------+---------+--------+---------+--------+---------+ 
| 681 | 19/10/2016 15:49 |   1 |  30 |  333 |  60 |  666 |  |   | 
| 682 | 19/10/2016 15:52 |   2 |  0 |  44 |  45 |  77 |  90 |  67 | 
+-------+------------------+-----------+--------+---------+--------+---------+--------+---------+ 

角度と長さの数は不明であり、任意の数の項目にすることができます。

は私がPIVOTについて読んますが、私は本当にために変更されたカラム(angle1angle2 ...)の、この例では、それを使用する方法がわからないと私はPIVOTは、いくつかの機能(MAXが必要であることを読んでいるので、 COUNT、...)と値が必要です...

+0

あなたが達成しようとしたことは、私たちに教えてください??希望の結果を得るためにピボットを使用してください –

+2

まだ何か試しましたか?ピボットクエリと呼ばれるものを探しています。しかし、角度の数が可変であれば、この問題を処理するには動的SQLが必要になることがあります。 –

+0

'sub_index'カラムが2番目のテーブルに混乱しているのがわかりました。あなたのために? – harshavmb

答えて

1

これを行うには、最初のクエリでもう1つ属性がありません。タイプと呼んでください。あなたは、あなたが望むことをするために、蛇口のクエリを使用することができます。

drop table if exists dbo.TableC; 

create table dbo.TableC (
_Index int 
, Date datetime 
, Sub_index int 
, Angle int 
, Length int 
, Type int 
); 


insert into dbo.TableC (_Index, Date, Sub_index, Angle, Length, Type) 
values (681, CONVERT(datetime, '19/10/2016 15:49', 103), 1, 30, 333, 1) 
, (681, CONVERT(datetime, '19/10/2016 15:49', 103), 1, 60, 666, 2) 
, (682, CONVERT(datetime, '19/10/2016 15:52', 103), 2, 0, 44, 1) 
, (682, CONVERT(datetime, '19/10/2016 15:52', 103), 2, 45, 77, 2) 
, (682, CONVERT(datetime, '19/10/2016 15:52', 103), 2, 90, 67, 3) 



select 
    t._Index, t.Date, t.Sub_index 
    , max(case when t.Type = 1 then t.Angle else null end) as Angle1 
    , max(case when t.Type = 1 then t.Length else null end) as Length1 
    , max(case when t.Type = 2 then t.Angle else null end) as Angle2 
    , max(case when t.Type = 2 then t.Length else null end) as Length2 
    , max(case when t.Type = 3 then t.Angle else null end) as Angle3 
    , max(case when t.Type = 3 then t.Length else null end) as Length3 
from dbo.TableC t 
group by t._Index, t.Date, t.Sub_index 
+0

ありがとう!! それはうまくいった! :) – user3584783

1

これは可能な動的ソリューションです。結果の表の列数は入力データに依存することに注意してください。これは通常は悪い考えです。このため、このコードをストアドプロシージャ内に配置するのは難しいでしょう。それにもかかわらず、ここで

は、あなたの質問に答える必要がありTSQL断片である:

--create a custom type that will be used in the final dynamic call 
if exists (select * from sys.types where name = 'TestTableType') 
    drop type TestTableType 
create type TestTableType as table([index] int,[sub_index] int, [data] nvarchar(max)) 

go 

--this table contains your input data 
declare @tem table([index] int, [date] datetime , [sub_index] int, [angle] decimal (19,6),[length] decimal (19,6)) 
--temp table used to calculate maximum number of columns to show 
declare @counters table([index] int,[sub_index] int, [counter] int) 
--temp table that will hold denormalized values (one row for each index/subindex couple) 
declare @denormalized_data TestTableType 
--this variables contains the maximum number of columns to show 
declare @max_columns int 
--this variable will contain the dunamically generated TSQL query that will give the final result 
declare @dynamic_query nvarchar(max) 
--support variables used to generate dynamic query 
declare @counter int 
declare @counter_str nvarchar(max) 

--1. populate input data 
insert into @tem select 681 , '20161019 15:49', 1 , 30, 333 
insert into @tem select 681 , '20161019 15:49', 1 , 60, 666 
insert into @tem select 682 , '20161019 15:52', 2 , 0, 44 
insert into @tem select 682 , '20161019 15:52', 2 , 45, 77 
insert into @tem select 682 , '20161019 15:52', 2 , 90, 67 
--insert into @tem select 682 , '20161019 15:52', 2 , 8, 88 

--2. calculate the number of columns to show 
insert into @counters 
select [index],[sub_index], COUNT(*) from @tem group by [index],[sub_index] 

select @max_columns = max([counter]) from @counters 

--3. denormalize data using an XML-based approach to obtain one row for each index/subindex couple 
insert into @denormalized_data 
SELECT 
    [index],[sub_index], 
'<MyData>'+ STUFF((
    SELECT ' <angle>' + CAST([angle] AS VARCHAR(MAX)) + '</angle><length>' + CAST([length] AS VARCHAR(MAX)) +'</length>' 
    FROM @tem 
    WHERE ([index] = Results.[index] and [sub_index] = Results.[sub_index]) 
    FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)') 
    ,1,2,'') + '</MyData>' AS NameValues 
FROM @tem Results 
GROUP BY [index],[sub_index] 

--4. generate a dynamic TSQL query with the correct number of columns 
set @counter = 0 
set @dynamic_query=' SELECT [index],[sub_index], ' 
while  @counter < @max_columns 
    begin 
    set @counter = @counter +1 
    set @counter_str = CAST(@counter as nvarchar(max)) 
    set @dynamic_query = @dynamic_query + ' CONVERT(XML,[data]).value(''/MyData[1]/angle['+ @counter_str + ']'',''varchar(100)'') AS angle'+ @counter_str + ', ' 
    set @dynamic_query = @dynamic_query + ' CONVERT(XML,[data]).value(''/MyData[1]/length['+ @counter_str + ']'',''varchar(100)'') AS length'+ @counter_str + ', ' 
    end 

set @dynamic_query = substring(@dynamic_query,1,LEN(@dynamic_query) - 1) + ' FROM @denormalized_d ' 

exec sp_executesql @dynamic_query, N'@denormalized_d TestTableType readonly', @denormalized_data 

ここでは3つの異なる値を持つ出力されます。ここでは

enter image description here

は、4つの異なる値(で出力されます行--insert into @tem select 682 , '20161019 15:52', 2 , 8, 88のコメントを外してください):

enter image description here

関連する問題