T-SQL 循环中多次自连接
T-SQL Multiple self-joins in a loop
我有一个 table,它在单个列中包含字段集合,我正在尝试将其构造为正确查看它自己行中的每个字段,如下例所示:
T_data:
+------+---------+---------+
| ID | Field | Value |
+------+---------+---------+
| 1 | Name | John |
| 1 | Age | 41 |
| 1 | Height | 181 |
| 2 | Name | Kelly |
| 2 | Age | 42 |
| 2 | Height | 165 |
| 3 | Name | Dan |
| 3 | Age | 43 |
| 3 | Height | 169 |
+------+---------+---------+
T_result:
+--------+--------+--------+--------+
| Name | John | Kelly | Dan |
| Age | 41 | 42 | 43 |
| Height | 181 | 165 | 169 |
+--------+--------+--------+--------+
我知道如何在同一个 table 上有 3 个自连接的示例中执行此操作,但这只是一个简化的示例,我的数据将有一个 ID 和字段的未知数量 - 我需要以某种方式遍历它们并将它们加入动态 table。
我将如何达到我的结果?
这是我的想法(行不通):
with #T_id as (
select distinct ID, row_number() over (order by ID asc) as rn form T_data )
-- here's where I need to loop through the IDs
-- Pseudo-code ... I know the following doesn't work
while @i <= (select count(*) from #T_id)
begin
select T_data.Field, T_data.Value from T_data
left join T_result on T_data.Field = T_result.Field
where T_data.ID = (select ID from #T_id where rn = @i)
end
编辑:最终结果是供 Reports Server 使用的存储过程。
任何帮助将不胜感激:)
PIVOT 很棒,但我使用动态数据透视的存储过程
Exec [prc-Pivot] 'YourTable','ID','max(Value)[]','Field','count(*)[Records]'
Returns
Field Records 1 2 3
Age 3 41 42 43
Height 3 181 165 169
Name 3 John Kelly Dan
存储过程
CREATE PROCEDURE [dbo].[prc-Pivot] (
@Source varchar(1000), -- Any Table or Select Statement
@PvotCol varchar(250), -- Field name or expression ie. Month(Date)
@Summaries varchar(250), -- aggfunction(aggValue)[optionalTitle]
@GroupBy varchar(250), -- Optional additional Group By
@OtherCols varchar(500) ) -- Optional Group By or aggregates
AS
--Exec [prc-Pivot] 'Select Year=Year(TR_Date),* From [Chinrus-Series].[dbo].[DS_Treasury_Rates]','''Q''+DateName(QQ,TR_Date)','avg(TR_Y10)[-Avg]','Year','count(*)[Records],min(TR_Y10)[Min],max(TR_Y10)[Max],Avg(TR_Y10)[Avg]'
--Exec [prc-Pivot] '#Temp','Attribute','max(Description)[]','ID','count(*)[Records]'
Set NoCount On
Set Ansi_Warnings Off
Declare @Vals varchar(max),@SQL varchar(max);
Set @Vals = ''
Set @OtherCols= IsNull(', ' + @OtherCols,'')
Set @Source = case when @Source Like 'Select%' then @Source else 'Select * From '+@Source end
Create Table #TempPvot (Pvot varchar(100))
Insert Into #TempPvot
Exec ('Select Distinct Convert(varchar(100),' + @PvotCol + ') as Pvot FROM (' + @Source + ') A')
Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot + ''' THEN '),')[', ' END),0) As [' + Pvot ) From #TempPvot Order by Pvot
Drop Table #TempPvot
Set @SQL = Replace('Select ' + Isnull(@GroupBy,'') + @OtherCols + @Vals + ' From (' + @Source + ') PvtFinal ' + case when Isnull(@GroupBy,'')<>'' then 'Group By ' + @GroupBy + ' Order by ' + @GroupBy else '' end,'Select , ','Select ')
--Print @SQL
Exec (@SQL)
Set NoCount Off
Set Ansi_Warnings on
枢轴 + 动态 SQL:
CREATE PROCEDURE dbo.ProcedureName
AS
BEGIN
SET NOCOUNT ON;
DECLARE @cols nvarchar(max),
@sql nvarchar(max)
SELECT @cols =COALESCE(@cols,'') +','+ QUOTENAME(ID) --,[1],[2],[3]
FROM T_data
GROUP BY ID
SET @sql = N'
SELECT *
FROM T_data
PIVOT (
MAX([Value]) FOR ID IN ('+STUFF(@cols,1,1,'')+')
) as dd'
EXEC sp_executesql @sql
END
输出:
Field 1 2 3
-------------------------------
Age 41 42 43
Height 181 165 169
Name John Kelly Dan
我有一个 table,它在单个列中包含字段集合,我正在尝试将其构造为正确查看它自己行中的每个字段,如下例所示:
T_data:
+------+---------+---------+
| ID | Field | Value |
+------+---------+---------+
| 1 | Name | John |
| 1 | Age | 41 |
| 1 | Height | 181 |
| 2 | Name | Kelly |
| 2 | Age | 42 |
| 2 | Height | 165 |
| 3 | Name | Dan |
| 3 | Age | 43 |
| 3 | Height | 169 |
+------+---------+---------+
T_result:
+--------+--------+--------+--------+
| Name | John | Kelly | Dan |
| Age | 41 | 42 | 43 |
| Height | 181 | 165 | 169 |
+--------+--------+--------+--------+
我知道如何在同一个 table 上有 3 个自连接的示例中执行此操作,但这只是一个简化的示例,我的数据将有一个 ID 和字段的未知数量 - 我需要以某种方式遍历它们并将它们加入动态 table。 我将如何达到我的结果?
这是我的想法(行不通):
with #T_id as (
select distinct ID, row_number() over (order by ID asc) as rn form T_data )
-- here's where I need to loop through the IDs
-- Pseudo-code ... I know the following doesn't work
while @i <= (select count(*) from #T_id)
begin
select T_data.Field, T_data.Value from T_data
left join T_result on T_data.Field = T_result.Field
where T_data.ID = (select ID from #T_id where rn = @i)
end
编辑:最终结果是供 Reports Server 使用的存储过程。
任何帮助将不胜感激:)
PIVOT 很棒,但我使用动态数据透视的存储过程
Exec [prc-Pivot] 'YourTable','ID','max(Value)[]','Field','count(*)[Records]'
Returns
Field Records 1 2 3
Age 3 41 42 43
Height 3 181 165 169
Name 3 John Kelly Dan
存储过程
CREATE PROCEDURE [dbo].[prc-Pivot] (
@Source varchar(1000), -- Any Table or Select Statement
@PvotCol varchar(250), -- Field name or expression ie. Month(Date)
@Summaries varchar(250), -- aggfunction(aggValue)[optionalTitle]
@GroupBy varchar(250), -- Optional additional Group By
@OtherCols varchar(500) ) -- Optional Group By or aggregates
AS
--Exec [prc-Pivot] 'Select Year=Year(TR_Date),* From [Chinrus-Series].[dbo].[DS_Treasury_Rates]','''Q''+DateName(QQ,TR_Date)','avg(TR_Y10)[-Avg]','Year','count(*)[Records],min(TR_Y10)[Min],max(TR_Y10)[Max],Avg(TR_Y10)[Avg]'
--Exec [prc-Pivot] '#Temp','Attribute','max(Description)[]','ID','count(*)[Records]'
Set NoCount On
Set Ansi_Warnings Off
Declare @Vals varchar(max),@SQL varchar(max);
Set @Vals = ''
Set @OtherCols= IsNull(', ' + @OtherCols,'')
Set @Source = case when @Source Like 'Select%' then @Source else 'Select * From '+@Source end
Create Table #TempPvot (Pvot varchar(100))
Insert Into #TempPvot
Exec ('Select Distinct Convert(varchar(100),' + @PvotCol + ') as Pvot FROM (' + @Source + ') A')
Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot + ''' THEN '),')[', ' END),0) As [' + Pvot ) From #TempPvot Order by Pvot
Drop Table #TempPvot
Set @SQL = Replace('Select ' + Isnull(@GroupBy,'') + @OtherCols + @Vals + ' From (' + @Source + ') PvtFinal ' + case when Isnull(@GroupBy,'')<>'' then 'Group By ' + @GroupBy + ' Order by ' + @GroupBy else '' end,'Select , ','Select ')
--Print @SQL
Exec (@SQL)
Set NoCount Off
Set Ansi_Warnings on
枢轴 + 动态 SQL:
CREATE PROCEDURE dbo.ProcedureName
AS
BEGIN
SET NOCOUNT ON;
DECLARE @cols nvarchar(max),
@sql nvarchar(max)
SELECT @cols =COALESCE(@cols,'') +','+ QUOTENAME(ID) --,[1],[2],[3]
FROM T_data
GROUP BY ID
SET @sql = N'
SELECT *
FROM T_data
PIVOT (
MAX([Value]) FOR ID IN ('+STUFF(@cols,1,1,'')+')
) as dd'
EXEC sp_executesql @sql
END
输出:
Field 1 2 3
-------------------------------
Age 41 42 43
Height 181 165 169
Name John Kelly Dan