2010-02-05 1 views
2

Доброе утро,Как использовать PIVOT в SQL Server 2005 хранимая процедура Вхождение два Вида

У меня 2 просмотры: ICCUDays, который содержит одну запись за счет с поля СЧЕТ и ICCUDays, ICCUEnctrSelectedRevCatsDirCost, который содержит несколько записей на счет с полями ACCOUNT, UBCATEGORY и DirectCost.

Моя цель: создать хранимую процедуру, которая выводит одну запись за каждый ACCOUNT с помощью ICCUDays и DirectCost по UBCATEGORY. Это будет кросс-таблица или сводчатая диаграмма и должна допускать возможность нулевых значений в одном или нескольких контейнерах со средней стоимостью. Наконец, эту кросс-таблицу или опорную точку необходимо отправить в новую таблицу EnctrUBCatPivot.

Вопросы: Каков правильный синтаксис PIVOT для вышеуказанного сценария? Учитывая, что я хочу отключить прямую стоимость для многих записей UBCATEGORY, как я могу написать TSQL для их повторения и поворота по учетной записи и UBCATEGORY? Все ли это выполняется в одном sproc, или его нужно разделить на несколько sprocs, чтобы записать результаты в таблицу?

Вот код, который я написал до сих пор:

ALTER PROCEDURE [dbo].[spICCUMain] 
-- Add the parameters for the stored procedure here 

AS 
declare @columns varchar(8000) 

BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON; 

-- Insert statements for procedure here 
SELECT @columns = COALESCE(@columns + ',[' + cast(UBCATEGORYmid as varchar) + ']','[' + cast(UBCATEGORYmid as varchar)+ ']') 
FROM vwICCUEnctrSelectedRevCatsDirCost 
GROUP BY UBCATEGORYmid 


DECLARE @query VARCHAR(8000) 

SET @query = ' 
SELECT * 
FROM vwICCUEnctrSelectedRevCatsDirCost 
PIVOT 
(
MAX(DirectCost) 
FOR [UBCATEGORYmid] 
IN (' + @columns + ') 
) 
AS p' 

EXECUTE(@query) 

END 

Это прекрасно работает в том, что он выдает счета и все прямые затраты на каждый UBCATEGORY. Тем не менее, мне нужно внутреннее соединение с vwICCUDAYS на ACCOUNT, чтобы добавить столбец в точку опоры для ICCUDays. Конечными опорными столбцами должны быть учетная запись, ICCUDays, Direct Cost для каждого UBCATEGORYmid.

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

Может ли кто-нибудь указать мне правильное направление? Спасибо, Sid

+0

Есть ли какая-то особая причина использовать представления в качестве основы для запроса? –

ответ

4

Вам необходимо знать все возможные значения для PIVOT. Таким образом, это трудно сделать с помощью T-SQL напрямую, если вы не используете динамический SQL, и это может стать довольно волосатым. Вероятно, лучше передать все строки обратно на уровень представления или автору отчета, и пусть он поворачивает их вбок.

Вот пример быстрого PIVOT, если вы заранее знаете все значения UBCategory. Я ушел из ICCUDays, так как это кажется неактуальным, если в нем нет столбцов из этой точки зрения.

USE tempdb; 
GO 
SET NOCOUNT ON; 
GO 

-- who on earth is responsible for your naming scheme? 
CREATE TABLE dbo.ICCUEnctrSelectedRevCatsDirCost 
(
    Account INT, 
    UBCategory VARCHAR(10), 
    DirectCost DECIMAL(9,2) 
); 

INSERT dbo.ICCUEnctrSelectedRevCatsDirCost 
    SELECT 1, 'foo', 5.25 
    UNION SELECT 1, 'bar', 6.25 
    UNION SELECT 1, 'smudge', 8.50 
    UNION SELECT 2, 'foo', 9.25 
    UNION SELECT 2, 'brap', 2.75; 

SELECT Account,[foo],[bar],[smudge],[brap] FROM 
    dbo.ICCUEnctrSelectedRevCatsDirCost 
    -- WHERE <something>, I assume ??? 
PIVOT 
(
    MAX(DirectCost) 
    FOR UBCategory IN ([foo],[bar],[smudge],[brap]) 
) AS p; 

GO 
DROP TABLE dbo.ICCUEnctrSelectedRevCatsDirCost; 

Чтобы сделать это более динамичным, вы должны получить список разделенных запятыми значений DISTINCT UBCategory и построить стержень на лету. Так может выглядеть следующим образом:

USE tempdb; 
GO 
SET NOCOUNT ON; 
GO 

-- who on earth is responsible for your naming scheme? 
CREATE TABLE dbo.ICCUEnctrSelectedRevCatsDirCost 
(
    Account INT, 
    UBCategory VARCHAR(10), 
    DirectCost DECIMAL(9,2) 
); 

INSERT dbo.ICCUEnctrSelectedRevCatsDirCost 
    SELECT 1, 'foo', 5.25 
    UNION SELECT 1, 'bar', 6.25 
    UNION SELECT 1, 'smudge', 8.50 
    UNION SELECT 2, 'foo', 9.25 
    UNION SELECT 2, 'brap', 2.75 
    UNION SELECT 3, 'bingo', 4.00; 

DECLARE @sql NVARCHAR(MAX), 
    @col NVARCHAR(MAX); 

SELECT @col = COALESCE(@col, '') + QUOTENAME(UBCategory) + ',' 
    FROM 
    (
     SELECT DISTINCT UBCategory 
     FROM dbo.ICCUEnctrSelectedRevCatsDirCost 
    ) AS x; 

SET @col = LEFT(@col, LEN(@col)-1); 

SET @sql = N'SELECT Account, $col$ FROM 
    dbo.ICCUEnctrSelectedRevCatsDirCost 
    -- WHERE <something>, I assume ??? 
PIVOT 
(
    MAX(DirectCost) 
    FOR UBCategory IN ($col$) 
) AS p;'; 

SET @sql = REPLACE(@sql, '$col$', @col); 

--EXEC sp_executeSQL @sql; 
PRINT @sql; 

GO 
DROP TABLE dbo.ICCUEnctrSelectedRevCatsDirCost; 

Затем «отправить данные в новую таблицу» вы можете просто сделать запрос INSERT INTO ... SELECT вместо прямой SELECT. Конечно, это кажется бесполезным, потому что для того, чтобы написать этот оператор insert, вам нужно знать порядок столбцов (который не гарантируется этим подходом), и вам нужно будет поместить столбцы для каждой потенциальной категории UBC все равно, так что это кажется очень цыпленком и яйцом.

+0

Итак, вы предлагаете разрешить SSRS 2005 делать группировку, поворот и т. Д.? Почему это целесообразно для использования Dynamic TSQL? Спасибо за разъяснение для меня :) – SidC

+0

Ну, я не уверен, что понимаю, как вы собираетесь «отправлять» данные в другую таблицу, если вы не знаете форму набора результатов.Если у вас есть UBC-категория, в которой требуется использовать динамический SQL для извлечения, как возможно, что в таблице назначения уже указан этот столбец? Передняя часть, безусловно, более гибкая в плане работы с подобным дисплеем. В любом случае, для хорошего учебника по динамическим плюсам и минусам SQL, см. Http://www.sommarskog.se/dynamic_sql.html –

+0

Большое спасибо за помощь! – SidC