按月汇总数据的分区行

Posted

技术标签:

【中文标题】按月汇总数据的分区行【英文标题】:Row over partition for totaling data by month 【发布时间】:2014-10-10 14:59:45 【问题描述】:

我有一些数据需要每月汇总,但我无法弄清楚如何让它有 12 列(每个月一列)以及当月的总和。

例子:

数据原样:

GrossAmt    ClaimDate
49764.00    2014-08-21 00:00:00.000
1382.43     2014-08-27 00:00:00.000
602.77      2014-09-02 00:00:00.000
497.04      2014-09-02 00:00:00.000

想要的结果:

GrossAmt    ClaimDate
51146.43    August
1099.81     September

实际期望的结果:

July  August    September
0     51146.43  1099.81

对不起,我之前没有包含这个!

我确信这是在分区上使用行的最基本示例,也许是我缺乏编程背景,但这是一个我无法理解的概念。

这是我目前所拥有的,但我不确定下一步该去哪里。

With CTE ([GrossAmt],ClaimMonth)
AS(
SELECT TOP 10000 
       Sum([GrossAmt]) as TotalClaimAmt
      ,CASE WHEN Month([ClaimDate]) = 1 THEN 'January'
            WHEN Month([ClaimDate]) = 2 THEN 'February'
            WHEN Month([ClaimDate]) = 3 THEN 'March'
            WHEN Month([ClaimDate]) = 4 THEN 'April'
            WHEN Month([ClaimDate]) = 5 THEN 'May'
            WHEN Month([ClaimDate]) = 6 THEN 'June'
            WHEN Month([ClaimDate]) = 7 THEN 'July'
            WHEN Month([ClaimDate]) = 8 THEN 'August'
            WHEN Month([ClaimDate]) = 9 THEN 'September'
            WHEN Month([ClaimDate]) = 10 THEN 'October'
            WHEN Month([ClaimDate]) = 11 THEN 'November'
            WHEN Month([ClaimDate]) = 12 THEN 'Decmber'
        End  AS ClaimMonth
  FROM [Database].[dbo].[Table]
    )
    Group BY  [ClaimDate]
    )
  Select * From CTE

也许我需要的是关于 Row over partition 如何工作的基本课程。我已经尝试阅读我在网上找到的文章,但对我来说似乎没有任何意义,它们是高级的,我马上就迷路了,而且我通过阅读没有很好地学习也无济于事,我需要看看在行动中,并了解它是如何工作的。

无论如何,感谢您的帮助。你们真棒! 编辑:

实际期望的结果:

July  August    September
0     51146.43  1099.81

对不起,我之前没有包含这个!

【问题讨论】:

你可以使用 DATENAME(MONTH,[ClaimDate]) 而不是那个尴尬的 CASE 表达式 【参考方案1】:

你需要使用PIVOT来获得想要的结果

CTE 进行每月聚合,PIVOT 用于将 CTE 结果行转换为水平列

;With CTE ([GrossAmt],MonthVal)
AS(
SELECT TOP 10000 
       Sum([GrossAmt]) as GrossAmt,
       DATEADD(MONTH, DATEDIFF(MONTH,0,ClaimDate), 0) as MonthVal
  FROM [Table1]
  Group BY  DATEADD(MONTH, DATEDIFF(MONTH,0,ClaimDate), 0)
)
SELECT * FROM
(Select [GrossAmt], DATENAME(MONTH,MonthVal) as ClaimMonth From CTE) t
PIVOT
( MAX(GrossAmt) for ClaimMonth  in 
  ( [January], [Febrauary], [March], [April], [May], [June], [July],  
    [August],  [September], [October], [November], [December] 

  )
)pvt

【讨论】:

2 很好的答案,但你也给出了很好的解释。谢谢你的解释。现在更有意义了。【参考方案2】:
DECLARE @Cols NVARCHAR(MAX);
SELECT @Cols =  STUFF((
                SELECT DISTINCT ', ' +  QUOTENAME(DATENAME(MONTH,ClaimDate))
                FROM TABLENAME
                FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,'')
DECLARE @Sql NVARCHAR(MAX);

SET @Sql  = 'SELECT ''GrossAmount'' AS AMOUNT_Sorted_By_DATE, 
' + @Cols +   '
FROM
(SELECT [GrossAmt], DATENAME(MONTH,ClaimDate) as ClaimMonth
FROM TABLENAME GROUP BY MONTH(ClaimDate)) AS SourceTable
PIVOT
(
SUM(GrossAmt)
FOR DATENAME(MONTH,ClaimDate) IN (' + @Cols +   ')
) AS PivotTable'
EXECUTE sp_executesql @Sql    

这将导致只有实际拥有数据的月数。

【讨论】:

【参考方案3】:
With CTE ([GrossAmt],ClaimMonth)
AS(
SELECT TOP 10000 
       Sum([GrossAmt]) as TotalClaimAmt
      ,DATENAME(MONTH, ClaimDate) AS ClaimMonth
  FROM [Database].[dbo].[Table]
  Group BY  DATENAME(MONTH, ClaimDate)
)
Select * From CTE

【讨论】:

我搞砸了我想要的结果。我的错。我实际上正在寻找这个:实际期望的结果:7 月 8 月 9 月 0 51146.43 1099.81【参考方案4】:
select top 1000 
       datename(month, [ClaimDate]), SUM([GrossAmt]) 
  from [Table] 
 group by datename(month, [ClaimDate])

【讨论】:

我没有对你投反对票,但我唯一能想到的就是这完美地回答了我原来的问题,但我发布的编辑基本上改变了整个问题。你回答了第一个。我的错。但你的与我最初发布的内容相符。

以上是关于按月汇总数据的分区行的主要内容,如果未能解决你的问题,请参考以下文章

如何将按月分区的配置单元表中的数据加载到按周分区的配置单元表中

如何在bigquery中按月创建分区

oracle表分区详解(按天按月按年等)

MySQL 表按月分区

Oracle普通表按月转分区表,通过PLSQL包一键生成分区表

Oracle普通表按月转分区表,通过PLSQL包一键生成分区表