Объединение нескольких динамических сводных таблиц

#sql #sql-server-2005 #pivot-table

#sql #sql-server-2005 #сводная таблица

Вопрос:

Я не видел подобного вопроса, но если есть такой, на который был дан ответ, пожалуйста, дайте мне знать.

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

Что мне нужно сделать, это динамически создать сводную таблицу и объединить ее с другой — или это то, что, как я думал, сработает.

Исходные данные работают аналогично этому (я изменил элементы для защиты данных моей компании):

Образец данных

Они хотят, чтобы данные выглядели в отчете следующим образом (для экономии места я использовал не все даты, но вы можете уловить идею): Пример отчета

Я создал временную таблицу и две динамические сводные таблицы. Обе таблицы будут работать отдельно, но как только я использую объединение ALL, я получаю сообщение об ошибке (я добавлю это ниже). Я включаю код, который я использовал для создания двух сводных таблиц. Может кто-нибудь сказать мне, что я делаю не так?

Возможно ли сделать это всего за один свод?

 /*
    Use dynamic SQL to find all 
    Issue Dates for column headings
*/
DECLARE @Jquery VARCHAR(8000)
DECLARE @query VARCHAR(4000)
DECLARE @years VARCHAR(2000)
SELECT  @years = STUFF(( SELECT DISTINCT
                        '],['   'Item 1'   ' '   (IssueDate)
                        FROM    #GroupData GroupData
                        ORDER BY '],['   'Item 1'   ' '   (IssueDate)
                        FOR XML PATH('')
                        ), 1, 2, '')   ']'

SET @query =
'SELECT * FROM
(
    SELECT LocationID, StoreName, StoreState AS State, "Item 1"   " "   (IssueDate) AS IssueDate, MoneyOrder
    FROM #GroupData GroupData
) MoneyOrderIssued
PIVOT (MAX(MoneyOrder) FOR IssueDate
IN (' @years ')) AS pvt'

DECLARE @queryMOUsed VARCHAR(4000)
DECLARE @MOUsedYear VARCHAR(2000)
SELECT  @MOUsedYear = STUFF(( SELECT DISTINCT
                        '],['   'Item 2'   ' '   (IssueDate)
                        FROM    #GroupData GroupData
                        ORDER BY '],['   'Item 2'   ' '   (IssueDate)
                        FOR XML PATH('')
                        ), 1, 2, '')   ']'

SET @queryMOUsed =
'SELECT * FROM
(
    SELECT LocationID, StoreName, StoreState AS State, "Item 2"   " "   (IssueDate) AS IssueDate, MOUsed
    FROM #GroupData GroupData
)SCRMoneyOrders
PIVOT (MAX(MOUsed) FOR IssueDate
IN (' @MOUsedYear ')) AS pvt'

SET @Jquery = @query   ' UNION ALL '    @queryMOUsed


EXECUTE (@query) -- Only in here to show that this works w/out UNION ALL
EXECUTE (@queryMOUsed) -- Only in here to show that this works w/out UNION ALL

EXECUTE (@Jquery)
  

Я получаю следующее сообщение об ошибке:

Предупреждение: Нулевое значение устраняется агрегированием или другой операцией НАБОРА. Сообщение 8114, уровень 16, состояние 5, ошибка в строке 1 при преобразовании типа данных varchar в bigint.

Ответ №1:

Моя идея заключается в том, что столбцы не совпадают (по количеству столбцов, порядку столбцов и типу данных). Если я правильно читаю ваш запрос, если даты выпуска для item1 и item2 не совпадают, вы все равно можете получить несоответствующие столбцы. Действительно трудно сказать, не видя выходных данных этих двух запросов.

Вы уверены, что не хотите ОБЪЕДИНЕНИЕ на основе идентификатора хранилища?

Что-то вроде :

 WITH Item1Data as (
--pivot query for item 1
),
Item2Data as (
 --pivot query for item 2
)
SELECT columns
FROM Item1DATA i1
LEFT JOIN Item2Data i2
ON i1.SoteID = i2.StoreID
  

Вот динамический запрос, который я выполнил. полученные столбцы генерируются данными:

  --Get string of aggregate columns for pivot.  The aggregate columns are the last 5 NRS Years.
                    DECLARE @aggcols NVARCHAR(MAX)

                    SELECT  @aggcols = STUFF(( SELECT   '],['
                                                          CAST(ny2.NRS_YEAR AS CHAR(4))
                                               FROM     mps.NRS_YEARS ny2
                                               WHERE    ny2.NRS_YEAR BETWEEN @NRS_Year
                                                        - 5 AND @NRS_Year
                                               ORDER BY '],['
                                                          CAST(ny2.NRS_YEAR AS CHAR(4))
                                             FOR
                                               XML PATH('') ) , 1 , 2 , '')
                              ']' ;

--While we're at it, get a sum of each year column.  we'll do a union query instead of  rollup because that's how we roll.

                    DECLARE @sumcols NVARCHAR(MAX) ;
                    SELECT  @sumcols = STUFF(( SELECT   ']),sum(['
                                                          CAST(ny2.NRS_YEAR AS CHAR(4))
                                               FROM     mps.NRS_YEARS ny2
                                               WHERE    ny2.NRS_YEAR BETWEEN @NRS_Year
                                                        - 5 AND @NRS_Year
                                               ORDER BY ']),sum(['
                                                          CAST(ny2.NRS_YEAR AS CHAR(4))
                                             FOR
                                               XML PATH('') ) , 1 , 3 , '')
                              '])' ;

                    DECLARE @Query NVARCHAR(MAX) ;
--Construct dynamic pivot query

                    SET @Query = N'SELECT MonthName as Month, '   @aggcols
                          N'
      into ##MonthHourPivot
FROM
 (SELECT nc.MONTHNAME, nc.MonthOfNRS_Yr, nc.NRS_YEAR, st.Hours
 FROM mps.NRS_Calendar nc 
 INNER JOIN dbo.StudentTime st
 ON nc.Date = /*00:00:00 AM*/ DATEADD(dd, DATEDIFF(dd, 0, /*On*/ st.EntryDateTime), 0)
 LEFT JOIN mps.vw_ScheduleRoomBuilding srb
 ON st.ScheduleID = srb.ScheduleID
 WHERE (st.EntryDateTime <= GETDATE() and st.SiteCode = '''   @SiteCode
                          N''' or '''   @SiteCode   N''' = ''All'')
 AND (srb.Abbreviation = '''   @Building   N''' or '''   @Building
                          N''' = ''All'')) p
 PIVOT
 (
 sum(p.Hours)
 FOR NRS_Year IN
( '   @aggcols   N' )
) AS pvt 
' ;

--Execute It.
                    EXECUTE(@Query) ;

                    SET @Query = N'Select [Month], '   @aggcols
                          N'FROM ##MonthHourPivot UNION ALL SELECT ''Total'' as [Month], '
                          @sumcols   ' FROM ##MonthHourPivot' ;
                     Execute (@Query);
  

Комментарии:

1. Я думаю, ты прав, Нейт. Наш администратор базы данных только что указал (как и пять минут назад), что я пытаюсь объединить два разных типа столбцов. На данный момент у нее не было ответа о том, как выполнить поворот для различных элементов, используя комбинацию дат. Есть мысли?

2. Еще один вопрос, нужно ли динамически генерировать элементы?

3. Это отличный вопрос. Мне действительно нужно, чтобы элементы генерировались динамически, потому что они основаны на датах из диапазона дат. Возможно, я не слишком хорошо это объяснил. единственный способ использовать все даты в качестве заголовков столбцов — это динамически создавать сводную таблицу. Позвольте мне попытаться объяснить это лучше: конечный пользователь введет диапазон дат и выберет магазин или магазины, которые они хотят видеть. Они хотят видеть продажи каждого товара за каждую дату. Итак, продажи для товара 1 на 8/20 рядом с продажами для товара 2 на 8/20.

4. Дайте мне секунду. Я пытаюсь найти какой-нибудь исходный код, с которым вы могли бы поработать.

5. Я обновил ответ динамическим запросом, который я сделал на основе year. Столбцы на 100% состоят из сгенерированных данных. Вы должны быть в состоянии адаптировать его, объединив строки элемента и даты.

Ответ №2:

Это кажется чем-то более подходящим для выполнения с помощью инструмента ETL.

Я не очень хорошо знаю набор инструментов Microsoft, но я предполагаю, что в их пакете для хранения данных есть что-то для этого. В программе Pentaho «Интеграция данных» (Kettle) вы бы использовали шаг денормализатора строк или шаг выравнивания строк.

Комментарии:

1. Спасибо за ответ. К сожалению, я не могу использовать ETL. Хранимая процедура, которую я создам с использованием этой сводной таблицы, будет перенесена в существующий продукт.