非常に単純なテーブルのピボットに苦労しています。 Web上のすべての例とチュートリアルは私が探しているものではないので、皆さんがここで私を助けることができるかもしれません(私のT-SQLの知識はそれほど良くないと言っておく必要があります...)
状況を説明しましょう:
私はテーブルを持っています
CREATE TABLE [dbo].[Trucks](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL)
SET IDENTITY_INSERT [dbo].[Trucks] ON
INSERT [dbo].[Trucks] ([Id], [Name]) VALUES (1, N'AAA-BBB')
INSERT [dbo].[Trucks] ([Id], [Name]) VALUES (2, N'AAA-CCC')
INSERT [dbo].[Trucks] ([Id], [Name]) VALUES (3, N'BBB-WWW')
INSERT [dbo].[Trucks] ([Id], [Name]) VALUES (4, N'SKL-POL')
INSERT [dbo].[Trucks] ([Id], [Name]) VALUES (5, N'QAS-ZSD')
SET IDENTITY_INSERT [dbo].[Trucks] OFF
各トラックにはコンパートメントがいくつかあります。各コンパートメントには名前と容量があります
CREATE TABLE [dbo].[Compartments](
[Id] [int] IDENTITY(1,1) NOT NULL,
[TruckId] [int] NOT NULL,
[Compartment] [nvarchar](50) NOT NULL,
[Capacity] [bigint] NULL)
SET IDENTITY_INSERT [dbo].[Compartments] ON
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (1, 1, N'C1', 5000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (2, 1, N'C2', 4000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (3, 1, N'C3', 5000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (4, 1, N'C4', 4000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (5, 1, N'C5', 6000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (6, 2, N'Vak 1', 6000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (8, 2, N'Vak 2', 6000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (9, 2, N'Vak 3', 5000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (10, 2, N'Vak 4', 5000)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (11, 3, N'1', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (12, 3, N'2', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (13, 3, N'3', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (14, 3, N'4', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (15, 3, N'5', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (16, 3, N'6', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (17, 3, N'7', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (18, 3, N'8', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (19, 3, N'9', 500)
INSERT [dbo].[Compartments] ([Id], [TruckId], [Compartment], [Capacity]) VALUES (20, 3, N'10', 500)
SET IDENTITY_INSERT [dbo].[Compartments] OFF
特定のトラックのコンパートメントのリストを返すSPを(TruckIdに基づいて)作成したいと思います。これは簡単な部分です:
SELECT * FROM COMPARTMENTS WHERE TruckId = @p_TruckId
これにより、次のようなテーブルが作成されます。
私がやりたいことは、ヘッダーとしてコンパートメント名、値として容量を持つテーブルを返すことです。
これは、値が1行だけのテーブルになります。列の数は、その特定のトラックのコンパートメントの数によって異なります。
PIVOT関数を調べましたが、そのためには事前に列数を知っておく必要があります。動的なPIVOTの例も見つけましたが、自分の状況でそれを機能させることができません。
ここで誰かが私を助けてくれますか?いいね!
編集: 私が見つけた例へのリンク
動的SQLクエリを作成する前に、構文を正しく取得できるように、常にハードコードされたバージョンを作成する必要があります。そのため、最初に行う必要があるのは、必要なTruckId
値のいずれかに対して機能するPIVOTクエリを記述することです。
静的バージョン:
あなたが必要だとしましょうTruckID = 3
、PIVOT
のコードは次のようになります。
select Name, TruckId, [1], [2], [3], [4], [5], [6]
from
(
select Name, TruckId, Compartment, Capacity
from Trucks t
inner join Compartments c
on t.Id = c.TruckId
where t.Id = 3 -- your truck id here
) d
pivot
(
max(capacity)
for compartment in ([1], [2], [3], [4], [5], [6]) -- your Compartment values here
) p;
動的バージョン:
ここでの問題は、Compartment
sにさまざまなTruckId
値を設定することになるため、TruckId
およびは、必要な結果を生成します。 PIVOT
関数は機能しますが、最初にSQL文字列を各Compartment
のすべてのTruckId
値と連結する必要があります。
まず、すべてのパラメーターを定義します。
DECLARE
@cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@ParmDefinition NVARCHAR(500),
@TruckId as int;
set @TruckId = 3; -- this would be the value you submit via your SP
set @ParmDefinition = '@id int';
次に、 FOR XML PATH および [〜#〜] stuff [〜#〜] を使用して、新しい列ヘッダーのリストを連結します。
select @cols = STUFF((SELECT ',' + QUOTENAME(Compartment)
from #Compartments
where TruckId = @TruckId
group by id, Compartment
order by Id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
列のリストを取得したら、実行される完全なSQL文字列を作成します。これは上記の静的バージョンに似ているはずです。
set @query
= N'SELECT Name, TruckId, ' + @cols + N'
from
(
select t.Name, c.TruckId, c.Compartment, c.Capacity
from #Trucks t
inner join #Compartments c
on t.Id = c.TruckId
where t.Id = @id
) x
pivot
(
max(Capacity)
for Compartment in (' + @cols + N')
) p ';
最後のステップは、sql文字列の実行です。
exec sp_executesql @query, @ParmDefinition, @id = @TruckId;
デモを見る 。これにより、次の結果が得られます。
Name TruckId 1 2 3 4 5 6 7 8 9 10
------- ------- --- --- --- --- --- --- --- --- --- ---
BBB-WWW 3 500 500 500 500 500 500 500 500 500 500