2011-01-16 4 views
0

요 전날 StackOverflow (stackoverflow.com/questions/4663698/how-can-i-display-a-consolidated-version-of-my-sql-server-table)에서 항목을 열었습니다. 그 당시 피벗 테이블에 데이터를 표시하는 방법에 대한 도움이 필요했습니다. 포럼에서 얻은 도움으로, 저의 연구는 동적 SQL에 대한이 페이지로 안내했습니다 : www.sommarskog.se/dynamic_sql.html. 그리고 Itzik Ben-Gan이 작성한 멋진 SQL 스크립트로 필자는 정확히 원하는 방식으로 피벗 테이블을 출력하는 저장 프로 시저를 만들었습니다 : sommarskog.se/pivot_sp.sp.SQL Server 피벗 테이블에서 미리 정의 된 열 이름

글쎄, 거의. 이 저장 프로 시저에서 하나의 변경이 필요합니다. SPROC의 @on_cols 변수에서 동적 열 이름을 가져 오는 대신 간단한 ASC 순서로 일반 열 이름을 저장하는 출력 테이블이 필요합니다. 예를 들어, col1, col2, col3, col4 ... 일 수 있습니다. 동적 열 이름은 저에게 문제입니다. 그래서 나는 그들이 나타나는 순서대로 그들의 색인에 의해 지명 된 그들을 필요로한다. 이 위대한 SQL 스크립트를 변경하는 모든 종류의 것들을 시도했지만 작동하지 않습니다.

너무 길기 때문에 작성자의 코드를 붙여 넣지 않았지만 above 링크가 표시됩니다.

도움을 주시면 감사하겠습니다.

답변

1

당신은

CREATE function dbo.values2table 
(
@values varchar(max), 
@separator varchar(3), 
@limit int -- set to -1 for no limit 
) returns @res table (id int identity, [value] varchar(max)) 
as 
begin 
declare @value varchar(50) 
declare @commapos int, @lastpos int 
set @commapos = 0 
select @lastpos = @commapos, @commapos = charindex(@separator, @values, @lastpos+1) 
while @commapos > @lastpos and @limit <> 0 
begin 
    select @value = substring(@values, @lastpos+1, @[email protected]) 
    if @value <> '' begin 
     insert into @res select ltrim(rtrim(@value)) 
     set @limit = @limit-1 
    end 
    select @lastpos = @commapos, @commapos = charindex(@separator, @values, @lastpos+1) 
end 
select @value = substring(@values, @lastpos+1, len(@values)) 
if @value <> '' insert into @res select ltrim(rtrim(@value)) 
return 
end 
GO 

그런 다음 (SQL 서버 지원 아래에 pivot_sp proc 디렉토리를 변경할 행으로 구분 된 목록 (열 이름)을 분할 유사한이 도우미 함수, 또는 뭔가가 필요 대단히 감사합니다 여러 줄의 문자열을, 그래서 나는 모든 "+ @newline +"의)

CREATE PROC dbo.pivot_sp 
    @query AS NVARCHAR(MAX), -- The query, can also be the name of a table/view. 
    @on_rows AS NVARCHAR(MAX), -- The columns that will be regular rows. 
    @on_cols AS NVARCHAR(MAX), -- The columns that are to be pivoted. 
    @agg_func AS NVARCHAR(257) = N'MAX', -- Aggregate function. 
    @agg_col AS NVARCHAR(MAX), -- Column to aggregate. 
    @generic AS bit = 0, 
    @debug AS bit = 1 
AS 

-- Input validation 
IF @query IS NULL OR @on_rows IS NULL OR @on_cols IS NULL 
    OR @agg_func IS NULL OR @agg_col IS NULL 
BEGIN 
    RAISERROR('Invalid input parameters.', 16, 1); 
    RETURN; 
END 

-- Additional input validation goes here (SQL Injection attempts, etc.) 

BEGIN TRY 
    DECLARE 
    @sql  AS NVARCHAR(MAX), 
    @cols AS NVARCHAR(MAX), 
    @newline AS NVARCHAR(2); 

    SET @newline = NCHAR(13) + NCHAR(10); 

    -- If input is a valid table or view 
    -- construct a SELECT statement against it 
    IF COALESCE(OBJECT_ID(@query, N'U'), 
       OBJECT_ID(@query, N'V')) IS NOT NULL 
    SET @query = N'SELECT * FROM ' + @query; 

    -- Make the query a derived table 
    SET @query = N'(' + @query + N') AS Query'; 

    -- Handle * input in @agg_col 
    IF @agg_col = N'*' 
    SET @agg_col = N'1'; 

    -- Construct column list 
    SET @sql = N' 
    SET @result = 
     STUFF(
     (SELECT N'','' + quotename(
      CAST(pivot_col AS sysname) 
      ) AS [text()] 
     FROM (SELECT DISTINCT ' 
      + @on_cols + N' AS pivot_col 
       FROM' + @query + N') AS DistinctCols 
     ORDER BY pivot_col 
     FOR XML PATH('''')) 
     ,1, 1, N'''');' 

    IF @debug = 1 
    PRINT @sql 

    EXEC sp_executesql 
    @stmt = @sql, 
    @params = N'@result AS NVARCHAR(MAX) OUTPUT', 
    @result = @cols OUTPUT; 

    DECLARE @colsout nvarchar(max) 
    if @generic = 1 
    select @colsout = coalesce(@colsout,'') + value + '] as col'+right(id,10) 
    from dbo.values2table(left(@cols, LEN(@cols)-1), '],[', -1) X 
    else 
    select @colsout = @cols 

    -- Create the PIVOT query 
    SET @sql = N' 
    SELECT ' + @on_rows + ',' + @colsout + ' 
     FROM (SELECT ' 
       + @on_rows 
       + N', ' + @on_cols + N' AS pivot_col' 
       + N', ' + @agg_col + N' AS agg_col 
      FROM ' + @query + N')' + 
       + N' AS PivotInput 
     PIVOT(' + @agg_func + N'(agg_col) 
     FOR pivot_col IN(' + @cols + N')) AS PivotOutput;' 

    IF @debug = 1 
     PRINT @sql 

    EXEC sp_executesql @sql; 

END TRY 
BEGIN CATCH 
    DECLARE 
    @error_message AS NVARCHAR(2047), 
    @error_severity AS INT, 
    @error_state AS INT; 

    SET @error_message = ERROR_MESSAGE(); 
    SET @error_severity = ERROR_SEVERITY(); 
    SET @error_state = ERROR_STATE(); 

    RAISERROR(@error_message, @error_severity, @error_state); 

    RETURN; 
END CATCH 
GO 

을 떨어 그리고 여기 당신이 어떤 SQL 서버 DB에서 실행 할 수 있어야 예입니다.

exec dbo.pivot_sp @query = ' 
select o.name object_name, c.system_type_id, c.name 
from sys.columns c 
inner join sys.objects o on o.object_id=c.object_id 
where o.is_ms_shipped = 0', 
@on_rows = 'object_name', 
@on_cols = 'system_type_id', 
@agg_func = N'COUNT', -- Aggregate function. 
@agg_col = 'name', 
@generic=1, 
@debug=1 
+0

안녕하세요, 사이버 위키, 귀하의 도움에 충분히 감사드립니다. 내 SPROC를 업데이트하고 매력처럼 작동합니다. –