Получение динамически генерируемой сводной таблицы во временную таблицу - PullRequest
4 голосов
/ 22 апреля 2009

Я видел это , поэтому я знаю, как создать сводную таблицу с динамически генерируемым набором полей. Моя проблема сейчас в том, что я хотел бы получить результаты во временную таблицу.

Я знаю, что для получения результирующего набора во временную таблицу из оператора EXEC необходимо предварительно определить временную таблицу. В случае динамически генерируемой сводной таблицы невозможно заранее узнать поля.

Единственный способ, с помощью которого я могу получить такую ​​функциональность, - это создать постоянную таблицу с использованием динамического SQL. Есть ли лучший способ?

Ответы [ 4 ]

2 голосов
/ 10 февраля 2016

Сегодня столкнулся с этой проблемой и разместил в моем блоге . Краткое описание решения - создать временную таблицу с одним столбцом, а затем динамически ее изменять, используя sp_executesql. Затем вы можете вставить в него результаты динамического PIVOT. Рабочий пример ниже.

CREATE TABLE #Manufacturers
(
    ManufacturerID INT PRIMARY KEY,
    Name VARCHAR(128)
)

INSERT INTO #Manufacturers (ManufacturerID, Name)
VALUES (1,'Dell')
INSERT INTO #Manufacturers (ManufacturerID, Name)
VALUES (2,'Lenovo')
INSERT INTO #Manufacturers (ManufacturerID, Name)
VALUES (3,'HP')

CREATE TABLE #Years
(YearID INT, Description VARCHAR(128))
GO

INSERT INTO #Years (YearID, Description) VALUES (1, '2014')
INSERT INTO #Years (YearID, Description) VALUES (2, '2015')
GO

CREATE TABLE #Sales
(ManufacturerID INT, YearID INT,Revenue MONEY)
GO

INSERT INTO #Sales (ManufacturerID, YearID, Revenue) VALUES(1,2,59000000000)
INSERT INTO #Sales (ManufacturerID, YearID, Revenue) VALUES(2,2,46000000000)
INSERT INTO #Sales (ManufacturerID, YearID, Revenue) VALUES(3,2,111500000000)
INSERT INTO #Sales (ManufacturerID, YearID, Revenue) VALUES(1,1,55000000000)
INSERT INTO #Sales (ManufacturerID, YearID, Revenue) VALUES(2,1,42000000000)
INSERT INTO #Sales (ManufacturerID, YearID, Revenue) VALUES(3,1,101500000000)
GO

DECLARE @SQL AS NVARCHAR(MAX)
DECLARE @PivotColumnName AS NVARCHAR(MAX)
DECLARE @TempTableColumnName AS NVARCHAR(MAX)
DECLARE @AlterTempTable AS NVARCHAR(MAX)

--get delimited column names for various SQL statements below
SELECT 
    -- column names for pivot
    @PivotColumnName= ISNULL(@PivotColumnName + N',',N'') + QUOTENAME(CONVERT(NVARCHAR(10),YearID)),
    -- column names for insert into temp table
    @TempTableColumnName = ISNULL(@TempTableColumnName + N',',N'') + QUOTENAME('Y' + CONVERT(NVARCHAR(10),YearID)),
    -- column names for alteration of temp table
    @AlterTempTable = ISNULL(@AlterTempTable + N',',N'') + QUOTENAME('Y' + CONVERT(NVARCHAR(10),YearID)) + ' MONEY' 
FROM (SELECT DISTINCT [YearID] FROM #Sales) AS Sales

CREATE TABLE #Pivot
(
     ManufacturerID INT
)

-- Thats it! Because the following step will flesh it out.

SET @SQL = 'ALTER TABLE #Pivot ADD ' + @AlterTempTable
EXEC sp_executesql @SQL

--execute the dynamic PIVOT query into the temp table 
SET @SQL =  N'
    INSERT INTO #Pivot (ManufacturerID, ' + @TempTableColumnName + ')
    SELECT ManufacturerID, ' + @PivotColumnName + '
    FROM #Sales S
    PIVOT(SUM(Revenue) 
      FOR S.YearID IN (' + @PivotColumnName + ')) AS PivotTable'
EXEC sp_executesql @SQL

SELECT M.Name, P.*
FROM #Manufacturers M
INNER JOIN #Pivot P ON M.ManufacturerID = P.ManufacturerID
1 голос
/ 22 апреля 2009

Позвольте мне попробовать это объяснение выбора в вместо. Я также использую SQL Server 2005. Поскольку у вас есть таблицы PIVOT, я собираюсь предположить то же самое или 2008 год.

select 
    o.*,
    OtherField1,
    OtherField2
INTO #temp
FROM
    OriginalOtherData as ood
PIVOT (
    MAX([Value])
    FOR Field in (OtherField1, OtherField2)
) as piv
RIGHT OUTER join
    Original o on o.OriginalSD = piv.OriginalSD

select * from #temp
Drop table #temp

Разница только между обычным выбором и выбором в состоит в том, что часть INTO #table.

1 голос
/ 22 апреля 2009

Вы могли бы сделать это:

-- add 'loopback' linkedserver 
if exists (select * from master..sysservers where srvname = 'loopback')
    exec sp_dropserver 'loopback'
go
exec sp_addlinkedserver @server = N'loopback',
    @srvproduct = N'',
    @provider = N'SQLOLEDB', 
    @datasrc = @@servername
go

declare @myDynamicSQL varchar(max)
select @myDynamicSQL = 'exec sp_who'
exec('
    select * into #t from openquery(loopback, ''' + @myDynamicSQL + ''');
    select * from #t
    ')

РЕДАКТИРОВАТЬ: добавлен динамический SQL для приема параметров в OpenQery

0 голосов
/ 17 апреля 2014
  • для запроса (выберите col1, col2, col3 из имени таблицы
  • col1 становится rowlabels
  • col2 становится заголовком столбца
  • col3 - набор данных

  • также избавляется от глобальной таблицы

    if OBJECT_ID('tempdb..#3') is not null drop table #3
    if OBJECT_ID('tempdb..##3') is not null drop table ##3
    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    select @cols = STUFF((SELECT distinct ',' + QUOTENAME(   col2    ) from    tablename    FOR XML PATH(''), col2).value('.', 'NVARCHAR(MAX)'),1,1,'')
    set @query = 'SELECT col1, ' + @cols + ' into ##3 from ( select col1, col2, col3 from tablename ) x  pivot (  max(col3)for col2 in (' + @cols + ')) p '
    execute(@query)   
    select * into #3 from ##3 if OBJECT_ID('tempdb..##3') -- is not null drop table ##3
    
...