【问题标题】:Creating Dynamic Pivot Table Column Names创建动态数据透视表列名
【发布时间】:2019-12-22 21:34:05
【问题描述】:

我创建了一个带有硬编码列名的数据透视表。数据透视表只是按数量(当月 + 11 个月前)保持销售额的滚动总和。

这是我第一次正确使用 PIVOT 功能,代码运行良好。

SELECT
    Item_Code_Desc,
    ISNULL([Current],0)     AS [Current],
    ISNULL([1],0)           AS [1],
    ISNULL([2],0)           AS [2],
    ISNULL([3],0)           AS [3],
    ISNULL([4],0)           AS [4],
    ISNULL([5],0)           AS [5],
    ISNULL([6],0)           AS [6],
    ISNULL([7],0)           AS [7],
    ISNULL([8],0)           AS [8],
    ISNULL([9],0)           AS [9],
    ISNULL([10],0)          AS [10],
    ISNULL([11],0)          AS [11]
FROM
    (SELECT
         CONCAT(ST.Code,' - ', ST.Description_1) AS Item_Code_Desc,
         STT.ActualQuantity AS Qty,
         CASE
            WHEN MONTH(STT.TxDate) = MONTH(GETDATE()) THEN 'Current'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -1, GETDATE())) THEN '1'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -2, GETDATE())) THEN '2'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -3, GETDATE())) THEN '3'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -4, GETDATE())) THEN '4'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -5, GETDATE())) THEN  '5'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -6, GETDATE())) THEN '6'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -7, GETDATE())) THEN '7'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -8, GETDATE())) THEN '8'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -9, GETDATE())) THEN   '9'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -10, GETDATE())) THEN '10'
            WHEN MONTH(STT.TxDate) = MONTH(DATEADD(MONTH, -11, GETDATE())) THEN '11'
            ELSE '0'
         END AS [Period]
     FROM 
         _bvSTTransactionsFull AS STT
     INNER JOIN 
         StkItem AS ST ON STT.AccountLink = ST.StockLink
     WHERE 
         STT.TxDate >= DATEADD(MONTH, -11, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
         AND STT.Module = 'AR') AS P
PIVOT  
    (SUM(P.Qty)
        FOR P.Period IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[Current])
    ) AS PVT

为了使输出更加动态,我希望将月份和年份显示为字段标题,而不仅仅是 1、2、3 等。

为了尝试这个,我先拿出了原来的CASE,用CONCAT函数得到了想要的结果

CONCAT(DATENAME(MONTH,STT.TxDate),' ',YEAR(STT.TxDate))                     AS [Period],

现在子查询以“mmmm yyyy”格式显示交易日期,我希望表格以此为轴心。当我快到最后时,我确实开始想知道它是如何做到这一点的,因为列名不再是硬编码的。

尝试后

 PIVOT (
            SUM(P.Qty)
        FOR  CONCAT(DATENAME(MONTH,P.TxDate),' ',YEAR(P.TxDate)) 
            ) AS PVT

我对许多其他变体进行了一些研究,发现这个过程比我想象的要复杂一些。

我以前没有使用过 STUFF 和 FOR XML PATH。我试图将上述内容转换为我在网上找到的示例。但我正在尝试,因为我不了解我正在尝试做的事情的核心逻辑。

请问我不仅可以帮助我了解如何获得枢轴动态,还可以提供一些注释以进一步了解正在发生的事情。非常感谢您对此的帮助!

尝试后

这是我尝试做对的尝试:

DECLARE
@Cols NVARCHAR(MAX),
@Query NVARCHAR(MAX),
@Module NVARCHAR = 'AR'

 SELECT 
@Cols = STUFF((SELECT DISTINCT ',' + 'CONCAT(DATENAME(MONTH, STT.TxDate),,YEAR(STT.TxDate))' + QUOTENAME(NAME)
                FROM _bvSTTransactionsFull AS STT
                WHERE STT.Module = 'AR'
                FOR XML PATH (''), TYPE).VALUE('.','NVARCHAR(MAX)'),1,1,'')
 SELECT
@Query = '
SELECT
Item_Code,
Item_Desc,
' +''''+ @Cols + '''''
FROM
 (SELECT
     ST.Code                                                                            AS Item_Code, 
     ST.Description_1                                                                   AS Item_Desc,
     STT.ActualQuantity                                                                 AS Qty,
     CONCAT(DATENAME(MONTH, STT.TxDate),,YEAR(STT.TxDate))                              AS [Period]
 FROM 
     _bvSTTransactionsFull AS STT
 INNER JOIN 
     StkItem AS ST ON STT.AccountLink = ST.StockLink
 WHERE 
     STT.TxDate >= DATEADD(MONTH, -13, DATEADD(MONTH, DATEDIFF(MONTH, 0, 
 GETDATE()), 0))
     AND STT.Module = '+ @Module +') AS P
 PIVOT  
(SUM(P.Qty)
    FOR P.Period IN ('+@cols+')
) AS PVT '
PRINT @Query
EXEC (@Query)

但我收到以下错误:

消息 207,第 16 级,状态 1,第 7 行 列名“NAME”无效。

我在哪里?

【问题讨论】:

标签: sql-server pivot


【解决方案1】:

您的结果在上面是正确的,但是您的列不会按正确的日期排序...

以下内容将满足这一点:

DECLARE
@Cols1  VARCHAR(MAX),
@Cols2  VARCHAR(MAX),
@Query  VARCHAR(MAX),
@Period VARCHAR(MAX) = -13 ; --/ Select number of months to view back on (excluding current month) \--


declare @tmptbl table (PeriodDate datetime, col1 varchar(100), col2 varchar(100))
insert into @tmptbl (PeriodDate, col1, col2)

SELECT DISTINCT dPeriodDate,'ISNULL('+ QUOTENAME(CONCAT(DATENAME(MONTH, dPeriodDate),' ',YEAR(dPeriodDate)))+',0) AS' + QUOTENAME(CONCAT(DATENAME(MONTH, dPeriodDate),' ',YEAR(dPeriodDate))) col1
,   QUOTENAME(CONCAT(DATENAME(MONTH, dPeriodDate),' ',YEAR(dPeriodDate))) col2
                FROM _bvSTTransactionsFull AS S join _etblPeriod p on EOMONTH(s.TxDate) = p.dPeriodDate
                WHERE S.Module = 'AR' AND S.TxDate > = DATEADD(MONTH, -13, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))

SELECT 
@Cols1 = STUFF((SELECT ',' + col1 
                FROM @tmptbl order by PeriodDate
                FOR XML PATH (''), TYPE).value('.','NVARCHAR(MAX)'),1,1,'')                     --/ allows the first SELECT fields to have the ISNULL function and Alias \--
SELECT
@Cols2 = STUFF((SELECT ',' + col2
                FROM @tmptbl order by PeriodDate
                FOR XML PATH (''), TYPE).value('.','NVARCHAR(MAX)'),1,1,'')  --/ becasue of the need for ISNULL above, second @Cols needed for the Pivot (pivot cannot have ISNULL in it) \--

SELECT
   @Query =
'SELECT
Item_Code_Desc,
'+@Cols1+'
FROM
(SELECT
     CONCAT(ST.Code,'' - '', ST.Description_1)                                  AS Item_Code_Desc,
     STT.ActualQuantity                                                         AS Qty,
     CONCAT(DATENAME(MONTH, STT.TxDate),'' '',YEAR(STT.TxDate))                 AS [Period]
 FROM 
     _bvSTTransactionsFull AS STT
 INNER JOIN 
     StkItem AS ST ON STT.AccountLink = ST.StockLink
 WHERE 
     STT.TxDate >= DATEADD(MONTH, '+@Period+', DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
     AND STT.Module = ''AR'') AS P
PIVOT  
(SUM(P.Qty)
    FOR P.Period IN ('+@cols2+')
) AS PVT '

PRINT @Query
EXEC (@Query)

我将我所做的更改保留在小写字母中,以便您查看更改...

【讨论】:

  • 发现了一个缺陷,July 列没有数量,但这是由于您的周期规范 - 它应该像您的列一样是 -13...在我的答案中编辑...
【解决方案2】:

解决了:)

DECLARE
@Cols1  VARCHAR(MAX),
@Cols2  VARCHAR(MAX),
@Query  VARCHAR(MAX),
@Period VARCHAR(MAX) = -12 ; --/ Select number of months to view back on (excluding current month) \--

SELECT 
@Cols1 = STUFF((SELECT DISTINCT ',' +'ISNULL('+ QUOTENAME(CONCAT(DATENAME(MONTH, S.TxDate),' ',YEAR(S.TxDate)))+',0) AS' + QUOTENAME(CONCAT(DATENAME(MONTH, S.TxDate),' ',YEAR(S.TxDate))) 
                FROM _bvSTTransactionsFull AS S
                WHERE S.Module = 'AR' AND S.TxDate > = DATEADD(MONTH, -13, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
                FOR XML PATH (''), TYPE).value('.','NVARCHAR(MAX)'),1,1,'')                     --/ allows the first SELECT fields to have the ISNULL function and Alias \--
SELECT
@Cols2 = STUFF((SELECT DISTINCT ',' + QUOTENAME(CONCAT(DATENAME(MONTH, S.TxDate),' ',YEAR(S.TxDate)))
                FROM _bvSTTransactionsFull AS S
                WHERE S.Module = 'AR' AND S.TxDate > = DATEADD(MONTH, -13, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
                FOR XML PATH (''), TYPE).value('.','NVARCHAR(MAX)'),1,1,'')  --/ becasue of the need for ISNULL above, second @Cols needed for the Pivot (pivot cannot have ISNULL in it) \--

SELECT
   @Query =
'SELECT
Item_Code_Desc,
'+@Cols1+'
FROM
(SELECT
     CONCAT(ST.Code,'' - '', ST.Description_1)                                  AS Item_Code_Desc,
     STT.ActualQuantity                                                         AS Qty,
     CONCAT(DATENAME(MONTH, STT.TxDate),'' '',YEAR(STT.TxDate))                 AS [Period]
 FROM 
     _bvSTTransactionsFull AS STT
 INNER JOIN 
     StkItem AS ST ON STT.AccountLink = ST.StockLink
 WHERE 
     STT.TxDate >= DATEADD(MONTH, '+@Period+', DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
     AND STT.Module = ''AR'') AS P
PIVOT  
(SUM(P.Qty)
    FOR P.Period IN ('+@cols2+')
) AS PVT '

PRINT @Query
EXEC (@Query)

【讨论】:

    猜你喜欢
    • 2014-10-18
    • 2022-10-04
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-06
    相关资源
    最近更新 更多