Sql server 2005 如何在连接两个视图的SQLServer2005存储过程中使用PIVOT

Sql server 2005 如何在连接两个视图的SQLServer2005存储过程中使用PIVOT,sql-server-2005,dynamic-pivot,Sql Server 2005,Dynamic Pivot,早上好 我有两个视图:ICCUDays,其中每个帐户包含一条记录,字段为account和ICCUDays;ICCUEnctrSelectedRevCatsDirCost,其中每个帐户包含多条记录,字段为account、UBCATEGORY和DirectCost 我的目标是:创建一个存储过程,按UBCATEGORY为每个帐户输出一条ICCUDays和DirectCost记录。这将是一个交叉表或支点,必须考虑到一个或多个直接成本类别区间中出现空值的可能性。最后,这个交叉表或数据透视需要发送到一个新表

早上好

我有两个视图:ICCUDays,其中每个帐户包含一条记录,字段为account和ICCUDays;ICCUEnctrSelectedRevCatsDirCost,其中每个帐户包含多条记录,字段为account、UBCATEGORY和DirectCost

我的目标是:创建一个存储过程,按UBCATEGORY为每个帐户输出一条ICCUDays和DirectCost记录。这将是一个交叉表或支点,必须考虑到一个或多个直接成本类别区间中出现空值的可能性。最后,这个交叉表或数据透视需要发送到一个新表EnctrUBCatPivot

问题:对于上述场景,正确的PIVOT语法是什么?考虑到我想要输出多少子类别条目的直接成本,我如何编写TSQL来迭代这些条目,并按帐户和子类别进行透视?所有这些都是在一个存储过程中完成的,还是必须将其分为多个存储过程才能将结果写入表中

以下是我迄今为止编写的代码:

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
这很好,因为它输出每个类别的帐户和所有直接成本。但是,我需要内部加入vwiccudies on ACCOUNT,以便为ICCUDays的pivot添加一列。最后的数据透视列应该是Account、ICCUDays和每个SubcategoryMid的直接成本

我不太熟悉coalesce语法,因此无法识别如何修改它以添加更多列,也不确定如何/在何处添加内部连接语法以添加ICCUDays

有人能给我指出正确的方向吗? 谢谢
Sid

您需要知道所有可能的数据透视值。因此,除非您使用动态SQL,否则直接使用T-SQL很难做到这一点,这可能会很快变得棘手。最好将所有行传递回表示层或报表编写器,并让它将它们横向翻转

如果您事先知道所有的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;
为了使其更具动态性,您必须获得逗号分隔的不同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语句,您需要知道列的顺序,而这种方法不能保证列的顺序,并且您需要已经为每个潜在的UBCategory值放入列,因此,这看起来很像鸡和蛋。

是否有任何特殊原因使用视图作为查询的基础?因此,您建议让SSRS 2005进行分组、旋转等操作。?为什么这比使用动态TSQL更可取?感谢您为我澄清:如果您不知道结果集的形状,我不确定我是否理解您将如何将数据发送到另一个表。如果有需要使用动态SQL进行检索的UBCategory,那么目标表如何可能已经定义了该列?在处理此类显示方面,前端肯定更灵活。无论如何,有关动态SQL优缺点的入门知识,请参阅: