如何按小计创建 SQL 组?

Posted

技术标签:

【中文标题】如何按小计创建 SQL 组?【英文标题】:How to create SQL grouped sub totals? 【发布时间】:2021-03-18 14:26:56 【问题描述】:

我有以下代码,按月和每个销售区域显示销售数据:

SELECT
   YEAR(date) as MyYear, DAB000.SalesRegion,
   type,
   SUM(CASE WHEN MONTH(date) =  1 THEN ROUND(value) END) as jan,
   SUM(CASE WHEN MONTH(date) =  2 THEN ROUND(value) END) as feb,
   SUM(CASE WHEN MONTH(date) =  3 THEN ROUND(value) END) as mar
   FROM
   (
      SELECT DAB020.*
      FROM
      (SELECT date, 'revenue' as type, value, buart, auf_kumsta,PERSNR FROM "DAB020.ADT"
      UNION ALL
      SELECT date, 'margin' as type, value - (menge*ekp/pe), buart, auf_kumsta,PERSNR FROM "DAB020.ADT"
      ) DAB020
      WHERE buart = 'A' AND auf_kumsta = 'J' AND date >= '2021-01-01'
     ) mysalesdata
     left join "DF030000.DBF" DAB000 on mysalesdata.PERSNR = DAB000.KDNR
 GROUP BY YEAR(date),DAB000.SalesRegion, type
 ORDER BY
    CASE WHEN DAB000.SalesRegion = 2 THEN 0
         WHEN DAB000.SalesRegion = 1 THEN 1
         WHEN DAB000.SalesRegion = 3 THEN 2
         WHEN DAB000.SalesRegion = 4 THEN 3
         WHEN DAB000.SalesRegion = 6 THEN 4
         WHEN DAB000.SalesRegion = 5 THEN 5
         ELSE 6 END, type DESC

感谢 @gordon-linoff 提供帮助!

结果如下所示:

MyYear  SalesRegion type    jan feb mar
2021    2   revenue 12345,00    12345,00    12345,00
2021    2   margin  12345,00    12345,00    12345,00
2021    1   revenue 12345,00    12345,00    12345,00
2021    1   margin  12345,00    12345,00    12345,00
2021    3   revenue 12345,00    12345,00    12345,00
2021    3   margin  12345,00    12345,00    12345,00
2021    4   revenue 12345,00    12345,00    12345,00

使用案例,我手动强制对销售区域进行分组。 2-1-3 和 4-6-5。

我想要的是每个分组(2-1-3 和 4-6-5)都有一个小计行。

像这样:

MyYear  SalesRegion type    jan feb mar
2021    2   revenue 12345,00    12345,00    12345,00
2021    2   margin  12345,00    12345,00    12345,00
2021    1   revenue 12345,00    12345,00    12345,00
2021    1   margin  12345,00    12345,00    12345,00
2021    3   revenue 12345,00    12345,00    12345,00
2021    3   margin  12345,00    12345,00    12345,00
Subtotal 2-1-3 - revenue    12345,00    12345,00    12345,00
Subtotal 2-1-3 - margin     12345,00    12345,00    12345,00    
2021    4   revenue 12345,00    12345,00    12345,00
.. and so on

问题是,我使用 Advantage 数据库,它没有 Pivot、Group By Rollup、cube 等或我一直在阅读的任何其他有用功能。

那么,有没有一种简单的方法可以在不使用此类函数的情况下将其添加到我当前的代码中?

【问题讨论】:

验证我的理解 - 您是指与此链接中描述的相同的 Advantage 数据库服务器 - 显示聚合功能可用吗? devzone.advantagedatabase.com/dz/content.aspx?Key=42&ID=49 嗨,是的 - 同一个数据库。我的 cmets 指的是 Advantage 没有某些功能,例如 Grouping Sets(例如:sqlservertutorial.net/sql-server-basics/…)。我确信必须有一种方法可以在没有此类功能且仅使用标准聚合技术的情况下做到这一点......但我不知道如何。这就是我在这里的原因:) 【参考方案1】:

好的 - 谢谢。

所以我在你原来的问题中查询了这一行

问题是,我使用 Advantage 数据库,它没有 Pivot、Group By Rollup、cube 等或我一直在阅读的任何其他有用的功能。

我发送的链接描述了使用 group by 来构建聚合

如果可能 - 使用原始代码 - 将 case 语句移出 order 子句以在 DAB000 表的末尾创建一个新的 [calculated] 列 - 并部署到视图中

第 1 步 - 将您的(细化)销售摘录部署到独立视图中

有一个额外的列显示SalesRegionOrder的偏好

偏好

创建视图 RegionSalesView as SELECT YEAR(DAB020.date) as MyYear, DAB000.SalesRegion, DAB000.SalesRegionOrder , 类型, SUM(CASE WHEN MONTH(DAB020.date) = 1 THEN ROUND(DAB020.value) END) 作为一月, 总和(CASE WHEN MONTH(DAB020.date)= 2 THEN ROUND(DAB020.value)END)为 2 月,总和(当月的情况(DAB020.date)= 3 THEN ROUND(DAB020.value) END) 作为 mar FROM ( 选择 DAB020.* 从 (SELECT .... ) 我的销售数据 左连接 ( 选择 *, CASE WHEN DAB000.SalesRegion = 2 THEN 0 ... 。 当 DAB000.SalesRegion = 5 THEN 5 ELSE 6 END 为 SalesRegionOrder 从 mysalesdata.PERSNR = DAB000.KDNR GROUP BYYEAR(DAB020.date),DAB000.SalesRegion, DAB000.SalesRegionOrder 上的“DF030000.DBF”DAB000 ) DAB000,DAB020。输入

第 2 步创建并维护一个新的自定义表 GroupRegions

元数据描述了您需要的确切报告级别

(为简洁起见,此处表示为 JSON,并且是说明性的)

 GroupRegions
GroupRegionsName :'2-1-3',
   SalesRegion : 2, GroupOrder : 0,
   SalesRegion : 1, GroupOrder : 1,
   SalesRegion : 3, GroupOrder : 2,
GroupRegionsName : '4',
   SalesRegion : 4, GroupOrder : 3,
GroupRegionsName : '6',
   SalesRegion : 6, GroupOrder : 4,
GroupRegionsName : '5',
   SalesRegion : 5, GroupOrder : 5

等等

第 3 步 -- SalesAggregations 在自己的视图中

构建一个新查询以从 RegionSalesView 和 GroupRegions- 中提取数据,使用 GroupRegions 名称创建聚合。

创建视图 GroupedRegionSalesView 为 选择 RegionSalesView.Myyear , GroupRegions.GroupRegionName , LastRegionOrdered+0.1 as GroupOrder , RegionSalesView.type , sum(RegionSalesView.jan) as jan , sum(RegionSalesView.feb) 作为 feb , sum(RegionSalesView.mar) 作为 mar 来自 RegionSales 在 GroupRegions.SalesRegion = RegionSalesView.SalesRegion 上内部加入 GroupRegions 内连接(选择 GroupRegionName, max(GroupOrder) as LastRegionOrdered 来自 GroupRegions 组,按 GroupRegionName) Orderer 在 Orderer.GroupRegionName = RegionSales.GroupRegionName 按 RegionSalesView.Myyear 分组 , GroupRegions.GroupRegionName , RegionSalesView.type )

第 4 步 - 将两者结合在一起

select RegionSalesView.Myyear
 , cast(RegionSalesView.SalesRegion as SalesRegion)
 , cast(GroupRegions.GroupOrder as float) as GroupRegions
 , RegionSalesView.type
 , RegionSalesView.jan
 , RegionSalesView.feb
 , RegionSalesView.mar 
 from RegionSalesView
union
select * from GroupedRegionSalesView 
order by GroupOrder, type

【讨论】:

感谢 ienerd,我会尽快解决这个问题并回复您! 看起来我无法创建视图(我想只有管理员可以这样做):(我可以调查任何替代方法来解决这个问题? 嗨,鸡蛋 - 作为数据开发人员,我们确实需要向 DBA 断言我们需要(不需要 - 必须拥有)正确的工具来正确完成工作。有了这样的限制,我只能建议您将表格的全部内容提取到文本文件中,并使用另一种技术来执行您的报告分析 - 例如 SQL Server,甚至 MS Excel 或 Python?您是否能够从 DBA 那里获得妥协以授予您查看创建权限? 您好,irnerd,感谢您的 cmets。长话短说,很可能不会。我会更容易找到替代方法。实际上,现在我基本上使用 PowerQuery SQL 连接将整个表转储到 Excel 中,然后根据需要处理数据。这里的任务是我尝试用“一站式 SQL 查询”替换整个 excel 工作。我目前正在边做边学。我确信我可以通过一些 SUM 和分组等来管理它......并使用你的代码作为灵感......我只需要解决它:) egg,你可以创建临时表而不是视图。唯一的区别是视图定义作为数据库的一部分被持久化,而临时表的定义是每个连接的临时表。所以,代替 CREATE VIEW AS SELECT ... FROM ... WHERE,您可以执行 SELECT ... INTO #whatever FROM ... WHERE .... 在后续查询中,您可以直接使用临时表作为SELECT ... FROM #whatever myTempTable WHERE ...

以上是关于如何按小计创建 SQL 组?的主要内容,如果未能解决你的问题,请参考以下文章

SQL如何使用JOIN创建小计

按 R 组小计

如何在 SQL 中使用其他表中的数据创建小计

如何避免在小计范围的第一行添加新行以保护小计公式

MS ACCESS:从总计小计中排除主要组的小计

Linq:获取具有多个嵌套组的内部对象的小计