按月和年透视表

时间:2014-01-07 23:11:23

标签: sql sql-server pivot sap

让我们从我已经拥有的查询开始,仅供参考:

/*Parameter Area*/
/*SELECT FROM [dbo].[OSRT] P0*/
declare @StartDate as datetime
/* WHERE */
set @StartDate = /* P0.FromDate */ '[%0]'

/*SELECT FROM [dbo].[OSRT] P1*/
declare @EndDate as datetime
/* WHERE */
set @EndDate = /* P1.ToDate */ '[%1]'

/* SELECT FROM [dbo].[OCRD] P2 */
declare @Vendor as varchar(30)
set @Vendor =  /* P2.CardCode */ '[%2]'

/* SELECT FROM [dbo].[OSRN] P4 */
declare @Serial as varchar(30)
set @Serial = /* P4.DistNumber */ '[%4]'


 declare @months as int
 declare @i as int
 declare @cols as NVARCHAR(MAX)
 set @months=MONTH(@EndDate)-Month(@StartDate)
 declare @query as NVARCHAR(MAX)

  SET @cols = STUFF((SELECT distinct ',' + (CONVERT(CHAR(4), c.DocDate, 100) + CONVERT(CHAR(4), c.DocDate, 120))
            FROM OPCH c
            WHERE (c.DocDate BETWEEN @StartDate and @EndDate)
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')



SET @query = 'Select Q1.CardCode, Q1.ItemCode, Q1.Dscription,'+  @cols +'

FROM (SELECT P1.CardCode, P1.DocDate, P2.ItemCode, P2.Dscription, P2.U_Unit, P2.U_UnitSer, P2.LineTotal FROM OPCH P1 INNER JOIN PCH1 P2 ON P1.DocEntry=P2.DocEntry) Q1 

WHERE (Q1.ItemCode Like ''PROM%'' AND Q1.CardCode=@Vendor AND Q1.DocDate BETWEEN @StartDate and @EndDate) OR (Q1.ItemCode Like ''PROM%'' AND Q1.U_UnitSer=@Serial AND Q1.DocDate BETWEEN @StartDate and @EndDate)

GROUP BY Q1.CardCode, Q1.ItemCode, Q1.Dscription

Pivot
(sum(Q1.LineTotal) FOR ((CONVERT(CHAR(4), Q1.DocDate, 100) + CONVERT(CHAR(4), Q1.DocDate, 120))) IN ('+@cols+')) P 

Order By Q1.CardCode ASC


FOR BROWSE'

Execute(@query)

现在,这个查询的大部分是用户提示的变量和动态生成的列,我已经知道这些列都有用。最基本的想法是生成一份针对员工和我们使用的车辆号码查询的费用报告,然后进行调整(按月分解,并通过添加年份进一步分类,以防我的最终用户决定做一些疯狂的事情,例如选择多年。)它按费用代码进行分组,并“希望”按照发生的月份分解这些费用。我知道可能有更简单的方法来获取这些数据,但是没有一个提供“专业”报告看起来我被要求提供

总而言之,我已经设法将我的主要问题跟踪到我正在使用的数据透视表。我的所有参数和动态内容都很好,所以我们可以把它放在一边用于测试目的,让整个查询更加干净。

让我们从几个表开始(我想尽可能地帮助测试):

Create table temp
(
DocEntry int,
DocDate DateTime,
CardCode NVARCHAR(50)
)

Create table templines
(
DocEntry int,
ItemCode NVARCHAR(50),
Dscription NVARCHAR(100),
U_Unit NVARCHAR(50),
U_UnitSer NVARCHAR(50),
LineTotal decimal(18,2)
)

我们也会插入一些值,只是为了简单起见:

Insert into temp (DocEntry,DocDate,CardCode)
VALUES
(1,'2013-08-08','Mike Ronnie'),
(2,'2013-09-09','Mike Ronnie'),
(3,'2013-08-10','GMC'),
(4,'2013-10-10','Mike Ronnie');

Insert into templines (DocEntry, ItemCode, Dscription, U_Unit, U_UnitSer, LineTotal)
Values
(1, 'PROM45', 'Misc Expenses', null, null, 175.89),
(1, 'PROM49', 'Hotel Expenses', null, null, 180.96),
(2, 'PROM45', 'Misc Expenses', null, null, 458.89),
(2, 'PROM38', 'Food Expenses', null, null, 222.58),
(2, 'PRO456', 'Random name', null, null, 1580.98),
(3, 'PROP589', 'Motor', 'PROE49', '400', 2897.36),
(3, 'PROM11', 'Service Labour', 'PROE49', '400', 333.89)
(4, 'PROM45', 'Misc Expenses', null, null, 150.48)

这应该给我一个不错的起点我希望并且应该模仿我希望以一种小的方式完成的事情。现在,我们将使用查询的精简版本,删除所有用户输入变量和基于此的动态生成,并将其替换为静态信息以进行测试:

Select Q1.CardCode, Q1.ItemCode, Q1.Dscription,[Aug 2013],[Feb 2013],[Jul 2013],[Jan 2013],[May 2013],[Sep 2013],[Dec 2013],[Oct 2013],[Mar 2013],[Jun 2013],[Apr 2013],
 Q1.LineTotal    
FROM (SELECT P1.CardCode, P1.DocDate, P2.ItemCode, P2.Dscription, P2.U_Unit, P2.U_UnitSer, P2.LineTotal FROM temp P1 INNER JOIN templines P2 ON P1.DocEntry=P2.DocEntry) Q1     
WHERE (Q1.ItemCode Like 'PROM%' AND Q1.CardCode='Mike Ronnie' AND Q1.DocDate BETWEEN DATEADD(year,-1,GETDATE()) and GETDATE())
 OR (Q1.ItemCode Like 'PROM%' AND Q1.U_UnitSer='400' AND Q1.DocDate BETWEEN DATEADD(year,-1,GETDATE()) and GETDATE())    
GROUP BY Q1.CardCode, Q1.ItemCode, Q1.Dscription    
Pivot
(
SUM(Q1.LineTotal)
 FOR 
 (
 CONVERT(CHAR(4), Q1.DocDate, 100)
  + CONVERT(CHAR(4), Q1.DocDate, 120)
  ) IN 
  ([Aug 2013],[Feb 2013],[Jul 2013],[Jan 2013],[May 2013],[Sep 2013],[Dec 2013],[Oct 2013],[Mar 2013],[Jun 2013],[Apr 2013])
  ) as P     

  Order By Q1.CardCode ASC       

  FOR BROWSE

现在是我遇到错误的地方:

第15行,第1行,第4行 关键字“Pivot”附近的语法不正确。

我承认,我对透视表没有足够的了解来解决我在这里做错的事。

对于大量的解释,我感到很遗憾,但是非常感谢您给我的任何帮助。

1 个答案:

答案 0 :(得分:2)

我相信你的问题与PIVOT语法有关。试一试:

SELECT CardCode, ItemCode, Dscription,
    [Aug 2013], [Feb 2013], [Jul 2013], [Jan 2013], [May 2013],
    [Sep 2013], [Dec 2013], [Oct 2013], [Mar 2013], [Jun 2013], [Apr 2013]
FROM (
    SELECT CONVERT(CHAR(4), P1.DocDate, 100) + CONVERT(CHAR(4), P1.DocDate, 120) AS DocDate,
        P1.CardCode, P2.ItemCode, P2.Dscription, P2.U_Unit, P2.U_UnitSer, P2.LineTotal
    FROM temp AS P1
        INNER JOIN templines AS P2 ON
            P1.DocEntry = P2.DocEntry
    WHERE (P2.ItemCode LIKE 'PROM%' AND P1.CardCode='Mike Ronnie' AND
        P1.DocDate BETWEEN DATEADD(YEAR, -1, GETDATE()) AND GETDATE()) OR
        (P2.ItemCode LIKE 'PROM%' AND P2.U_UnitSer='400' AND P1.DocDate BETWEEN
            DATEADD(YEAR, -1, GETDATE()) AND GETDATE())) AS src
PIVOT (
    SUM(LineTotal) FOR src.DocDate IN ([Aug 2013], [Feb 2013], [Jul 2013], [Jan 2013],
        [May 2013], [Sep 2013], [Dec 2013], [Oct 2013], [Mar 2013], [Jun 2013], [Apr 2013])
    ) AS pvt

这里的主要变化是所有“源数据”都被推入单个内联FROM子句(“源表”),这是PIVOT正常工作所必需的。我确实删除了一个GROUP BY语句,因此请仔细检查以确保数据按预期出现(如果需要,将其重新添加到内联源表中)。如果您想要一行总计,则需要在SELECT语句中添加每个月,并考虑NULL(例如ISNULL([Aug 2013], 0) + ISNULL([Feb 2013], 0) +...)。