동적으로 피벗된 데이터를 반환하는 SQL 함수
문제
MSSQL에서 속성을 취하고 피벗 함수를 사용하여 연결된 SQL 문을 생성하는 테이블 반환 함수를 갖는 것이 가능합니까?
CREATE FUNCTION dbo.fnPivot (@EntityTypeID int)
RETURNS TABLE
AS
BEGIN
DECLARE @SQL varchar(MAX);
DECLARE @COLS varchar(MAX);
select @COLS=coalesce(@COLS+',','')+'['+Name+']'from c_EntityAttribute WHERE EntityTypeID = @EntityTypeID;
SET @SQL = 'SELECT * FROM (SELECT EntityInstanceID, AttributeName, Value FROM v_EntityElementData WHERE EntityTypeID = 1) as s';
SET @SQL = @SQL + 'PIVOT ( MIN(Value) FOR AttributeName IN (' + @COLS + ') ) AS p';
RETURN EXEC sp_ExecuteSQL @SQL ;
END
해결책
불행하게도 저장 프로시저를 제외하고 SQL Server는 모든 뷰, 함수 등의 출력에 대한 테이블 정의를 추적합니다.따라서 열과 유형은 입력 시 동적으로 변경될 수 없습니다.
이러한 이유로 저는 PIVOT 연산자가 유용하다고 생각한 적이 없습니다.일반적으로 다양한 열 데이터를 가져오는 유일한 방법은 이를 XML로 처리하는 것입니다.
무슨 이유로 돌리는 걸까요?이는 일반적으로 UI 문제이므로 UI나 SSRS 등에서 수행하는 것이 좋습니다.
다른 팁
테이블 값 기능은 항상 지정된 스키마를 반환해야하므로 불가능합니다.
다음은 이런 종류의 기능을 수용하기 위해 한 일이 있습니다 (관점에서 볼 때 함수는 동일한 방법론을 따릅니다). 우리는 모든 설치 스크립트의 끝에 갇혀 있었기 때문에 테이블이 피벗되는 테이블을 변경하면 다시 생성 된보기에서 픽업됩니다.
IF EXISTS (SELECT *
FROM sys.objects
WHERE object_id = Object_id(N'[dbo].[vwYourView]')
AND type IN ( N'V' ))
BEGIN
DROP VIEW [dbo].[vwYourView]
END
GO
Declare @cols VARCHAR(MAX)
Select @cols = COALESCE(@cols + ',[' + YourColumn+ ']',
'[' + YourColumn+ ']')
FROM YourTable
Order By YourColumn
DECLARE @query VARCHAR(MAX)
Set @query =
N'
Create View vwYourView
AS
Select * FROM YourTable
Pivot (
MAX(YourVal)
FOR YourColumn IN( '+
@cols
+')
) AS pvt
'
Execute(@query)
Select * FROM [vwYourView]
나는 테이블의 모든 값을 동적으로 피벗하기위한 다음 절차를 만들었습니다.
CREATE OR ALTER PROC dbo.spDynamicPivot (
@Query NVARCHAR(MAX) --The query to pivot
, @AggregateFunction NVARCHAR(MAX) --The aggregation function surrounding the column name to be pivoted
, @ValueColumn NVARCHAR(MAX) --The value column from which to create columns
, @ResultTable NVARCHAR(MAX) = NULL --An optional table name into which the results will be stored. Note, this unfortunately will not work with #temp tables.
) AS BEGIN
SET XACT_ABORT ON;
SET NOCOUNT ON;
DECLARE @cols NVARCHAR(MAX);
DECLARE @sql NVARCHAR(MAX) = 'SELECT @cols = ISNULL(@cols + '','', '''') + ''['' + Val + '']'' FROM (SELECT DISTINCT Val = ' + @ValueColumn + ' FROM (' + @Query + ') a) b;';
DECLARE @paramDef NVARCHAR(MAX) = '@cols NVARCHAR(MAX) OUTPUT';
EXEC sp_executesql @sql, @paramDef, @cols = @cols OUTPUT;
DECLARE @resultSetSql NVARCHAR(MAX) = IIF(ISNULL(@ResultTable, '') <> '', 'INTO ' + @ResultTable + ' ', '');
SET @sql = 'SELECT * ' + @resultSetSql + 'FROM (' + @Query + ') q PIVOT( ' + @AggregateFunction + ' FOR ' + @ValueColumn + ' IN (' + @cols + ') ) p';
EXEC sp_executesql @sql;
END
용법:
DROP TABLE IF EXISTS #t;
CREATE TABLE #t (Name VARCHAR(50), Age INT, NetWorth FLOAT);
INSERT INTO #t VALUES
('Bill', 50, 250),
('Barb', 17, 15),
('Fred', 25, 30),
('Bill', 25, 100),
('Kahless', 90000, 4E10)
--Displaying results directly
EXEC dbo.spDynamicPivot @Query = 'SELECT * FROM #t', @AggregateFunction = 'AVG(NetWorth)', @ValueColumn = 'Name'
--Or writing them into a table for additional use
DROP TABLE IF EXISTS tempdb.dbo.MyTable;
EXEC dbo.spDynamicPivot @Query = 'SELECT * FROM #t', @AggregateFunction = 'AVG(NetWorth)', @ValueColumn = 'Name', @ResultTable = 'tempdb.dbo.MyTable'
SELECT * FROM tempdb.dbo.MyTable
제휴하지 않습니다 StackOverflow