连接表并根据映射对特定数据求和
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
但是,老实说,设计很糟糕。
我正在努力学习 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
但是,老实说,设计很糟糕。