Mr.*_* T. 8 sql-server pivot t-sql
我正在努力旋转一个非常简单的表格。网络上的所有示例和教程,都不是我要找的,所以也许你们可以在这里帮助我(我必须说我的 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
Run Code Online (Sandbox Code Playgroud)
每辆卡车都有一定数量的隔间。每个隔间都有名称和容量
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
Run Code Online (Sandbox Code Playgroud)
我想编写一个 SP,它返回某个卡车的隔间列表(基于 TruckId)。这是简单的部分:
SELECT * FROM COMPARTMENTS WHERE TruckId = @p_TruckId
Run Code Online (Sandbox Code Playgroud)
这给了我一个看起来像这样的表:
我想要做的是返回一个以隔间名称作为标题和容量作为值的表。
这将是一个只有 1 行值的表格。列的数量取决于给定卡车的隔间数量。
我查看了 PIVOT 函数,但您需要提前知道列数。我还找到了一个动态 PIVOT 示例,但我似乎无法让它在我的情况下工作。
有人可以在这里帮助我吗?那很好啊!
编辑:我找到的例子的链接
Tar*_*ryn 13
在编写动态 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;
Run Code Online (Sandbox Code Playgroud)
动态版本:
现在,您的问题是您将拥有Compartment
任何TruckId
s的各种值,因此您需要编写一些可以接受任何值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';
Run Code Online (Sandbox Code Playgroud)
接下来,您将使用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,'');
Run Code Online (Sandbox Code Playgroud)
获得列列表后,您将创建将要执行的完整 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 ';
Run Code Online (Sandbox Code Playgroud)
最后一步是执行sql字符串:
exec sp_executesql @query, @ParmDefinition, @id = @TruckId;
Run Code Online (Sandbox Code Playgroud)
查看演示。这给出了以下结果:
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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
17325 次 |
最近记录: |