2011-01-16 6 views
0

neulich öffnete ich ein Thema hier in StackOverflow (stackoverflow.com/questions/4663698/how-can-i-display-a-consolidated-version-of-my-sql-server-table). Zu dieser Zeit brauchte ich Hilfe, um Daten auf einer Pivot-Tabelle anzuzeigen. Von der Hilfe, die ich hier im Forum bekam, führte mich meine Forschung zu dieser Seite über dynamisches SQL: www.sommarskog.se/dynamic_sql.html. Und dann führte es mich zu diesem großartigen SQL-Skript von Itzik Ben-Gan, das eine gespeicherte Prozedur erstellt, die eine Pivot-Tabelle genau so ausgibt, wie ich es möchte: sommarskog.se/pivot_sp.sp.Vordefinierte Spaltennamen in SQL Server Pivot-Tabelle

Nun, fast. Ich brauche eine Änderung in dieser gespeicherten Prozedur. Anstatt dynamische Spaltennamen aus der Variablen @on_cols im SPROC zu ziehen, muss die Ausgabetabelle allgemeine Spaltennamen in einfacher ASC-Reihenfolge enthalten. Könnte zum Beispiel col1, col2, col3, col4 sein ... Die dynamischen Spaltennamen sind ein Problem für mich. Also brauche ich sie nach ihrem Index benannt in der Reihenfolge, in der sie erscheinen. Ich habe alle möglichen Dinge versucht, dieses großartige SQL-Skript zu ändern, aber es wird nicht funktionieren.

Ich habe den Code nicht vom Autor eingefügt, weil es zu lang ist, aber der Link above wird uns dorthin bringen.

Jede Hilfe wird geschätzt. Vielen Dank

Antwort

1

Sie benötigen diese Hilfsfunktion, oder etwas ähnliches eine begrenzte Liste (die Spaltennamen) zu Reihen

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 

dann die pivot_sp proc, um die Änderung unter (SQL Server unterstützt aufzuspalten mehrzeiligen Strings, so ließ ich alle „+ @NewLine +“ s)

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 

Und hier ist ein Beispiel sollten Sie von jedem beliebigen SQL Server db ausgeführt werden können.

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

Hallo, cyberwiki, ich kann dir nicht genug für deine Hilfe danken. Mein SPROC aktualisiert und funktioniert wie ein Zauber. –

Verwandte Themen