SQL Server에서 '피벗'을 사용하여 행을 열로 변환
MS 피벗 테이블의 내용을 읽었으며 여전히이 문제를 해결하는 데 문제가 있습니다.
생성되는 임시 테이블이 있는데, 열 1은 상점 번호이고 열 2는 주 번호이며 마지막으로 열 3은 일부 유형의 총계입니다. 또한 주 번호는 동적이며 상점 번호는 정적입니다.
Store Week xCount
------- ---- ------
102 1 96
101 1 138
105 1 37
109 1 59
101 2 282
102 2 212
105 2 78
109 2 97
105 3 60
102 3 123
101 3 220
109 3 87
다음과 같이 피벗 테이블로 나오기를 원합니다.
Store 1 2 3 4 5 6....
-----
101 138 282 220
102 96 212 123
105 37
109
측면과 주 아래에 숫자를 저장하십시오.
SQL Server 2005+를 사용하는 경우이 PIVOT
함수를 사용 하여 데이터를 행에서 열로 변환 할 수 있습니다 .
주를 알 수없는 경우 동적 SQL을 사용해야하는 것처럼 들리지만 처음에 하드 코딩 된 버전을 사용하여 올바른 코드를 보는 것이 더 쉽습니다.
먼저 다음은 빠른 테이블 정의 및 사용할 데이터입니다.
CREATE TABLE #yt
(
[Store] int,
[Week] int,
[xCount] int
);
INSERT INTO #yt
(
[Store],
[Week], [xCount]
)
VALUES
(102, 1, 96),
(101, 1, 138),
(105, 1, 37),
(109, 1, 59),
(101, 2, 282),
(102, 2, 212),
(105, 2, 78),
(109, 2, 97),
(105, 3, 60),
(102, 3, 123),
(101, 3, 220),
(109, 3, 87);
값을 알고 있으면 쿼리를 하드 코딩합니다.
select *
from
(
select store, week, xCount
from yt
) src
pivot
(
sum(xcount)
for week in ([1], [2], [3])
) piv;
SQL 데모 보기
그런 다음 주 번호를 동적으로 생성해야하는 경우 코드는 다음과 같습니다.
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(Week)
from yt
group by Week
order by Week
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT store,' + @cols + ' from
(
select store, week, xCount
from yt
) x
pivot
(
sum(xCount)
for week in (' + @cols + ')
) p '
execute(@query);
SQL 데모를 참조하십시오 .
동적 버전 week
은 열로 변환해야하는 숫자 목록을 생성합니다 . 둘 다 동일한 결과를 제공합니다.
| STORE | 1 | 2 | 3 |
---------------------------
| 101 | 138 | 282 | 220 |
| 102 | 96 | 212 | 123 |
| 105 | 37 | 78 | 60 |
| 109 | 59 | 97 | 87 |
동적 주 수입니다.
전체 예 : SQL Dynamic Pivot
DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT @ColumnName= ISNULL(@ColumnName + ',','') + QUOTENAME(Week)
FROM (SELECT DISTINCT Week FROM #StoreSales) AS Weeks
--Prepare the PIVOT query using the dynamic
SET @DynamicPivotQuery =
N'SELECT Store, ' + @ColumnName + '
FROM #StoreSales
PIVOT(SUM(xCount)
FOR Week IN (' + @ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql @DynamicPivotQuery
하위 쿼리를 사용하여 이전과 동일한 결과를 얻었습니다. 따라서 원래 테이블의 이름이 StoreCountsByWeek이고 스토어 ID가 나열된 별도의 테이블이있는 경우 다음과 같습니다.
SELECT StoreID,
Week1=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=1),
Week2=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=2),
Week3=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=3)
FROM Store
ORDER BY StoreID
이 방법의 한 가지 장점은 구문이 더 명확하고 다른 테이블에 조인하여 다른 필드를 결과로 가져 오는 것이 더 쉽다는 것입니다.
내 일화 결과는 1 초 이내에 완료된 2 천 행에 대해이 쿼리를 실행하고 실제로 7 개의 하위 쿼리가 있다는 것입니다. 그러나 주석에서 언급 했듯이이 방법을 사용하면 계산 비용이 많이 들기 때문에 많은 양의 데이터에서 실행될 것으로 예상되는 경우이 방법을 사용하는 데주의하십시오.
이것이 당신이 할 수있는 일입니다 :
SELECT *
FROM yourTable
PIVOT (MAX(xCount)
FOR Week in ([1],[2],[3],[4],[5],[6],[7])) AS pvt
이 목적에 유용 할 수있는 sp를 작성 중입니다. 기본적 으로이 sp는 테이블을 피벗하고 새 테이블을 피벗하거나 데이터 세트 만 반환합니다.이를 실행하는 방법입니다.
Exec dbo.rs_pivot_table @schema=dbo,@table=table_name,@column=column_to_pivot,@agg='sum([column_to_agg]),avg([another_column_to_agg]),',
@sel_cols='column_to_select1,column_to_select2,column_to_select1',@new_table=returned_table_pivoted;
참고하시기 바랍니다 매개 변수 @agg에 열 이름이 함께해야 '['
하고, 매개 변수는 쉼표로 끝나야합니다','
SP
Create Procedure [dbo].[rs_pivot_table]
@schema sysname=dbo,
@table sysname,
@column sysname,
@agg nvarchar(max),
@sel_cols varchar(max),
@new_table sysname,
@add_to_col_name sysname=null
As
--Exec dbo.rs_pivot_table dbo,##TEMPORAL1,tip_liq,'sum([val_liq]),sum([can_liq]),','cod_emp,cod_con,tip_liq',##TEMPORAL1PVT,'hola';
Begin
Declare @query varchar(max)='';
Declare @aggDet varchar(100);
Declare @opp_agg varchar(5);
Declare @col_agg varchar(100);
Declare @pivot_col sysname;
Declare @query_col_pvt varchar(max)='';
Declare @full_query_pivot varchar(max)='';
Declare @ind_tmpTbl int; --Indicador de tabla temporal 1=tabla temporal global 0=Tabla fisica
Create Table #pvt_column(
pivot_col varchar(100)
);
Declare @column_agg table(
opp_agg varchar(5),
col_agg varchar(100)
);
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(@table) AND type in (N'U'))
Set @ind_tmpTbl=0;
ELSE IF OBJECT_ID('tempdb..'+ltrim(rtrim(@table))) IS NOT NULL
Set @ind_tmpTbl=1;
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(@new_table) AND type in (N'U')) OR
OBJECT_ID('tempdb..'+ltrim(rtrim(@new_table))) IS NOT NULL
Begin
Set @query='DROP TABLE '+@new_table+'';
Exec (@query);
End;
Select @query='Select distinct '+@column+' From '+(case when @ind_tmpTbl=1 then 'tempdb.' else '' end)+@schema+'.'+@table+' where '+@column+' is not null;';
Print @query;
Insert into #pvt_column(pivot_col)
Exec (@query)
While charindex(',',@agg,1)>0
Begin
Select @aggDet=Substring(@agg,1,charindex(',',@agg,1)-1);
Insert Into @column_agg(opp_agg,col_agg)
Values(substring(@aggDet,1,charindex('(',@aggDet,1)-1),ltrim(rtrim(replace(substring(@aggDet,charindex('[',@aggDet,1),charindex(']',@aggDet,1)-4),')',''))));
Set @agg=Substring(@agg,charindex(',',@agg,1)+1,len(@agg))
End
Declare cur_agg cursor read_only forward_only local static for
Select
opp_agg,col_agg
from @column_agg;
Open cur_agg;
Fetch Next From cur_agg
Into @opp_agg,@col_agg;
While @@fetch_status=0
Begin
Declare cur_col cursor read_only forward_only local static for
Select
pivot_col
From #pvt_column;
Open cur_col;
Fetch Next From cur_col
Into @pivot_col;
While @@fetch_status=0
Begin
Select @query_col_pvt='isnull('+@opp_agg+'(case when '+@column+'='+quotename(@pivot_col,char(39))+' then '+@col_agg+
' else null end),0) as ['+lower(Replace(Replace(@opp_agg+'_'+convert(varchar(100),@pivot_col)+'_'+replace(replace(@col_agg,'[',''),']',''),' ',''),'&',''))+
(case when @add_to_col_name is null then space(0) else '_'+isnull(ltrim(rtrim(@add_to_col_name)),'') end)+']'
print @query_col_pvt
Select @full_query_pivot=@full_query_pivot+@query_col_pvt+', '
--print @full_query_pivot
Fetch Next From cur_col
Into @pivot_col;
End
Close cur_col;
Deallocate cur_col;
Fetch Next From cur_agg
Into @opp_agg,@col_agg;
End
Close cur_agg;
Deallocate cur_agg;
Select @full_query_pivot=substring(@full_query_pivot,1,len(@full_query_pivot)-1);
Select @query='Select '+@sel_cols+','+@full_query_pivot+' into '+@new_table+' From '+(case when @ind_tmpTbl=1 then 'tempdb.' else '' end)+
@schema+'.'+@table+' Group by '+@sel_cols+';';
print @query;
Exec (@query);
End;
GO
다음은 실행 예입니다.
Exec dbo.rs_pivot_table @schema=dbo,@table=##TEMPORAL1,@column=tip_liq,@agg='sum([val_liq]),avg([can_liq]),',@sel_cols='cod_emp,cod_con,tip_liq',@new_table=##TEMPORAL1PVT;
그런 다음 Select * From ##TEMPORAL1PVT
반환합니다
select * from (select name, ID from Empoyee) Visits
pivot(sum(ID) for name
in ([Emp1],
[Emp2],
[Emp3]
) ) as pivottable;
위의 @Tayrn answer 개정판은 피벗을 좀 더 쉽게 이해하는 데 도움이 될 수 있습니다.
이것이 최선의 방법은 아니지만 테이블 피벗 방법에 대해 머리를 감싸는 데 도움이되었습니다.
ID = 피벗하려는 행
MY_KEY = 피벗하려는 열 이름이 포함 된 원본 테이블에서 선택하는 열입니다.
VAL = 각 열에서 반환하려는 값입니다.
MAX (VAL) => 다른 집계 함수로 대체 할 수 있습니다. SUM (VAL), MIN (VAL) 등
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(MY_KEY)
from yt
group by MY_KEY
order by MY_KEY ASC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ID,' + @cols + ' from
(
select ID, MY_KEY, VAL
from yt
) x
pivot
(
sum(VAL)
for MY_KEY in (' + @cols + ')
) p '
execute(@query);
다른 데이터베이스가이 문제를 어떻게 해결하는지 알려주세요. DolphinDB
또한 피벗을 기본적으로 지원하며 SQL이 훨씬 직관적이고 깔끔하게 보입니다. 키 열 ( Store
), 피벗 열 ( Week
) 및 계산 된 메트릭 ( sum(xCount)
) 을 지정하는 것만 큼 간단 합니다.
//prepare a 10-million-row table
n=10000000
t=table(rand(100, n) + 1 as Store, rand(54, n) + 1 as Week, rand(100, n) + 1 as xCount)
//use pivot clause to generate a pivoted table pivot_t
pivot_t = select sum(xCount) from t pivot by Store, Week
DolphinDB는 컬럼 형 고성능 데이터베이스입니다. 데모의 계산 비용은 dell xps 랩탑 (i7 cpu)에서 546ms에 불과합니다. 자세한 내용은 온라인 DolphinDB 매뉴얼 https://www.dolphindb.com/help/index.html?pivotby.html을 참조하십시오.
참고 URL : https://stackoverflow.com/questions/15931607/convert-rows-to-columns-using-pivot-in-sql-server
'Programing' 카테고리의 다른 글
C # 6.0은 .NET 4.0에서 작동합니까? (0) | 2020.03.27 |
---|---|
java.sql.ResultSet의 크기는 어떻게 얻습니까? (0) | 2020.03.27 |
제거하지 않고 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES를 처리하는 방법 (0) | 2020.03.27 |
이 '느린 네트워크가 감지되었습니다…'로그가 Chrome에 표시되는 이유 (0) | 2020.03.27 |
시스템의 차이. (0) | 2020.03.27 |