连接表并根据映射对特定数据求和

Join tables and sum specific data based on a mapping

我正在努力学习 SSMS 并且我正在尝试做这件事。我有这个 table 叫做 CompanyGroup:

| SourceCompanyId | TargetCompanyId  |
| ---  | ------ |
| 4626 | 359468 |
| 4626 | 7999   |
| 56167| 11947  |

这 table 代表属于同一组的公司。例如,如果我是公司 4626,那么我的公司组将由 [4626, 359468, 7999] 组成,如果我是公司 7999,我的公司组仍将是 [4626, 359468, 7999]。因此,如果我是公司 56167,我的公司组就是 [56167, 11947]

还有另一个 table 叫销售:

| CompanyId| Product| Sales|
|:-----|:-------| ------|
| 4626  | Monitors| 1000|
| 4626  | Locks   | 300|
| 359468| Chairs  | 500|
| 359468| Lights  | 300|
| 7999  | Chairs  | 500|
| 4626  | Locks   | 300|
| 56167 | Locks   | 1000|
| 11947 | Tables  | 300|

这个table代表一个公司的销售额。

当您“选择”该组中的任何一家公司时,我正在处理此查询以获取每个公司组的总销售额,例如:对于组 4626,总销售额为 2300。

到目前为止,这是我的查询:

SELECT
    s.CompanyId,
    SUM(s.Sales) AS 'Sales'
    FROM Sales AS s
    JOIN CompanyGroup AS cg ON s.SourceCompanyId = cg.CompanyId
    WHERE s.CompanyId = 4626
    GROUP BY s.CompanyId

结果是这样的

|CompanyId | Sales  |
| -------- | ------ |
| 4626     | 1600   |

但是我只想得到整个集团公司的销售总额,例如:

| Sales  |
| ------ |
| 2900   |

我只是不确定如何添加使其对当前组中其他公司的数据求和并将它们加在一起。

虽然您是SQL的新手,但您的数据结构只会带来麻烦。可以查询吗?是的,但更难。我首先想建议一种替代方法来识别“组”。创建第二个 table 组,然后让所有公司与该组相关联。你甚至可以有一些 clear-text 组的内容,例如

CompanyGroups
CompanyGroupID  CompanyGroupName
1               Eastern Group
2               Northern Group
3               Technical Group
4               Furniture Group

Then the companies
SourceCompanyId  CompanyGroupID
4626             3
359468           3
7999             3
56167            4
11947            4

因此,每个公司和关联的已知组都有一个记录。

如果一家公司可以可能与多个组相关联,那么每个公司和备用组也可以有额外的记录。

现在,回到定期安排的节目和您的查询。您需要有一个“通用”组,以便关联所有目标,包括 组中的基础源公司,例如您的 4626 是源,另外两个 359468、7999是一样的。它扩展了另一个答案,但将 left-most ID 强制置于主要位置。

select distinct
      SourceCompanyID as GrpParent,
      SourceCompanyID as IncludedCompany
   from
      CompanyGroup cg
UNION
select
      cgParent.SourceCompanyID as GrpParent,
      cgTarget.TargetCompanyId as IncludedCompany
   from
      CompanyGroup cgParent
         JOIN CompanyGroup cgTarget
            on cgParent.SourceCompanyID = cgTarget.SourceCompanyID

请注意,查询的第一部分是获取 source 一次,即使它们与其他五个目标相关联。我们不想因为重复来源而重复计数。它拥有自己的 ID 作为母公司 将作为 part-of 组包含的公司。

第二个再次从同一父级开始,但获得 目标 作为包含的公司。所以,基于你的数据

SourceCompanyId  TargetCompanyId
4626             359468
4626             7999
56167            11947

结果为

GrpParent   IncludedCompany
-- first the distinct portion before union
4626        4626
56167       56167
-- now the union portion
4626        359468
4626        7999
56167       11947

你可以看到总共五条记录,4626“集团”显示了所有三个公司 ID,包括它自己在 right-side,类似地,56167 有两个条目,每个条目都在包含的公司 right-side.

现在有了这个,你应该可以加入GROUP的数据求和,而不会造成重复聚合。

select
      CompGrps.GrpParent,
      sum( CompSales.Sales ) as GroupTotalSales
   from
      ( select distinct
              SourceCompanyID as GrpParent,
              SourceCompanyID as IncludedCompany
           from
              CompanyGroup cg
        UNION
        select
              cgParent.SourceCompanyID as GrpParent,
              cgTarget.TargetCompanyId as IncludedCompany
           from
              CompanyGroup cgParent
                 JOIN CompanyGroup cgTarget
                    on cgParent.SourceCompanyID = cgTarget.SourceCompanyID
       ) as CompGrps
         JOIN
         ( SELECT
                 s.CompanyId,
                 SUM(s.Sales) AS Sales
              FROM
                 Sales s
             group by
                 s.CompanyId ) CompSales
            on CompGrps.IncludedCompany = CompSales.CompanyID
   group by
      CompGrps.GrpParent
   order by
      sum( CompSales.Sales ) desc

所以请注意第一个查询得到不同的集团公司,从它自己的二次查询 per-company sales 可以加入到它自己的公司 ID 上,但是根据共同的集团父级求和,从而给出总计每个 GROUP 的外层。

我还添加了一个简单的 order by 以获得最大的销售额排序在顶部。如您所见,现有结构有点混乱,但可以完成。

输出应该类似于

GrpParent  GroupTotalSales
4626       2900       (4626 had 1600, 359468 had 800, and 7999 had 500)
56167      1300       (56167 had 1000, 11947 had 300)

基于(错误的)隐含假设,即任何未列为目标公司的公司因此都是集团公司...

SELECT
  COALESCE(c.SourceCompanyId, s.CompanyId)   AS GroupCompanyId,
  SUM(s.Sales)   AS Sales
FROM
  Sales          s
LEFT JOIN
  CompanyGroup   c
    ON c.TargetCompanyId = s.CompanyId
GROUP BY
  COALESCE(c.SourceCompanyId, s.CompanyId)

演示:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=0fbc8e7d00625d3eae72e1763c9e2688

但是,老实说,设计很糟糕。