如何将我的 SQL 聚合 Rollup 限制为特定分组?

How do I restrict my SQL aggregation Rollups to a specific grouping?

以下 SQL returns 5 个分组列和两个聚合列:

select ten.TenancyName,
       svd.EmployeeId,
       usr.DisplayName,
       tjt.JobTitle,
       tjc.Name as JobCategory,
       count(svd.ratingpoints) as NumReviews, 
       avg(svd.ratingpoints) as Rating 
  from surveydetails svd
  join AbpUsers usr on usr.Id = svd.EmployeeId
  join AbpTenants ten on ten.Id = usr.TenantId
  join TenantJobTitle tjt on tjt.TenantId = usr.TenantId and tjt.Id = usr.JobTitleId
  join TenantJobTitleCategories tjc on tjc.Id = tjt.JobTitleCategory
 where svd.employeeid is not null
   and svd.CreationTime > '2020-01-01'
   and svd.CreationTime < '2021-12-31'
 group by ten.TenancyName,
          rollup(svd.EmployeeId,
                 usr.DisplayName,
                 tjt.JobTitle,
                 tjc.Name)
order by ten.TenancyName,
         svd.EmployeeId,
         usr.DisplayName,
         tjt.JobTitle,
         tjc.[Name]

我确实希望汇总到 TenancyName 级别,但它不需要所有其他中间汇总行。事实上,您可以看到从 Doctor(Employee)的行向上滚动到 EmployeeId 在每一行上产生完全相同的值,因为这些是一对一的数据属性。唯一有意义的级别是 TenancyName 级别,因为每个租户中有多个医生。

事后,我可以使用 HAVING 子句或将其作为外部 select 的子 select 来消除不需要的行,后者将过滤掉不需要的行。例如:

   select ten.TenancyName,
      svd.EmployeeId,
      usr.DisplayName,
      tjt.JobTitle,
      tjc.Name as JobCategory,
      count(svd.ratingpoints) as NumReviews, 
      avg(svd.ratingpoints) as Rating 
 from surveydetails svd
 join AbpUsers usr on usr.Id = svd.EmployeeId
 join AbpTenants ten on ten.Id = usr.TenantId
 join TenantJobTitle tjt on tjt.TenantId = usr.TenantId and tjt.Id = usr.JobTitleId
 join TenantJobTitleCategories tjc on tjc.Id = tjt.JobTitleCategory
where svd.employeeid is not null
  and svd.CreationTime > '2020-01-01'
  and svd.CreationTime < '2021-12-31'
group by ten.TenancyName,
         rollup(svd.EmployeeId,
                usr.DisplayName,
                tjt.JobTitle,
                tjc.Name)
having (svd.EmployeeId is null and 
        usr.DisplayName is null and 
        tjt.JobTitle is null and 
        tjc.Name is null)
       or
       (ten.TenancyName is not null and 
        svd.EmployeeId is not null and 
        usr.DisplayName is not null and 
        tjt.JobTitle is not null and 
        tjc.Name is not null)
order by ten.TenancyName,
         svd.EmployeeId,
         usr.DisplayName,
         tjt.JobTitle,
         tjc.[Name]

这提供了我想要的,但如果这可以通过 group by / rollup 结构自然地完成,我认为从简单性和性能的角度来看,这将是更可取的。

大多数支持 rollup 的数据库也支持 grouping sets。我更喜欢 grouping sets 因为它可以让您明确控制组。

例如,如果您想按所有列、租期进行分组,并有一个总行,您可以使用:

group by grouping sets ( (ten.TenancyName, svd.EmployeeId, usr.DisplayName, tjt.JobTitle, tjc.Name),
                         (ten.TenancyName),
                         ()
                       )