根据角色类型来自 3 个表的分层数据
Posted
技术标签:
【中文标题】根据角色类型来自 3 个表的分层数据【英文标题】:Hierarchical data from 3 tables according to the role type 【发布时间】:2013-10-04 07:35:00 【问题描述】:以下是我的表格:
[用户管理员]
UserId Int, UserName Varchar(200),AddedBy Int
UserId EmpName AddedBy
1 admin 0
2 SubAdmin1 1
3 Vikas 2
4 Mohit 3
5 Atul 4
6 Vishal 2
7 Mani 3
8 Sunny 1
[销售大师]
SalesId Int, UserId Int (FK_UserMaster_UserId) , Price Int
SalesId UserId Price StatusId
10 1 100 1
11 2 200 1
12 3 300 1
13 4 500 1
14 5 100 2
15 6 200 1
16 7 111 2
17 8 222 1
[销售产品]
SaleProductId Int, SaleId Int (FK_SaleMaster_SaleId) , Quantity Int
SaleProductId SalesId Quantity
1 10 2
2 11 2
3 12 1
4 13 1
5 14 3
6 15 2
7 16 5
8 17 1
[输出]
结果集应该有登录用户的销售额+他创建的用户和他们的子用户创建的更多用户。
以下 TotalSalesAmount 是:
[SalesMaster].Price * [SalesProducts].Quantity
例如:UserId: 1 的总销售额是 100*2+200*2+ 300*1 + 500*1 +100*3 + 200*2 +111*5 + 222*1= 2877
同样对于 UserId: 2 是 200*2+300*1 + 200*2 +500*1 + 111*5 +200*2= 2555
案例一:
如果 (admin)UserId=1 将登录,我们需要显示以下内容
UserId TotalSalesAmount OwnSaleAmount AddedBy
1 2877 200 0
2 2555 400 1
3 1355 300 2
4 800 500 3
5 100*3= 300 300 4
6 200*2=200 200 2
7 111*5= 555 555 3
8 222*1= 222 222 1
案例 2: 如果 (Vikas)UserId=3 将登录,我们需要显示以下内容
UserId TotalSalesAmount OwnSaleAmount AddedBy
3 300*1 + 500*1 + 111*5= 1355 300 2
4 500*1 + 100*3= 800 500 3
5 100*3= 300 300 4
7 111*5= 555 555 3
我用过的表格脚本和数据在这里 http://test-admin.teamberry.biz/SalesScript.rar ,
运行此脚本后请执行以下查询 take UM.UserId=164, SM.statusID = 1 UserId=166 的 TotalSalesAmount 出错了,因为它的 TotalSaleAmount 应该与 ownSaleAmount 相同,即 444,因为 UserId=166 没有任何孩子。
with tblOwnSaleAmount as
(
select UM.UserId,UM.EmpName,UM.AddedBy,cast(sum( SM.Price*SP.Quantity) as int) as OwnSaleAmount
from UserMaster UM
left join SalesMaster SM on SM.UserId = UM.UserId and SM.statusID = 1
left join SalesProducts SP on SP.SalesId = SM.SalesId
where UM.UserId = 164
group by UM.UserId ,UM.AddedBy,UM.EmpName
union all
select UM.UserId,UM.EmpName, UM.AddedBy,
case when SM.statusID = 1 then cast(( SM.Price*SP.Quantity ) as int)
else 0 end as OwnSaleAmount
from UserMaster UM
join tblOwnSaleAmount on tblOwnSaleAmount.UserId = UM.AddedBy
join SalesMaster SM on SM.UserId = UM.UserId
join SalesProducts SP on SP.SalesId = SM.SalesId
)
, tbldistinctOwnSaleAmount as
(
select distinct UserId,EmpName, AddedBy,Isnull(OwnSaleAmount,0) as OwnSaleAmount
from tblOwnSaleAmount
)
,
tblTotalOwnSaleAmount as
(
select OSA.UserId,OSA.EmpName, OSA.AddedBy, sum( OSA.OwnSaleAmount ) as OwnSaleAmount
from tbldistinctOwnSaleAmount OSA --inner join tbldistinctOwnSaleAmount A on OSA.AddedBy = A.UserID
group by OSA.UserId ,OSA.AddedBy,OSA.EmpName
)
select OSA.*
, TotalSalesAmount = isnull(
(
select sum( OSA1.OwnSaleAmount )
from tblTotalOwnSaleAmount OSA1
where OSA1.UserId > OSA.UserId
), 0 )
+ OSA.OwnSaleAmount
from tblTotalOwnSaleAmount OSA
order by OSA.UserId
【问题讨论】:
【参考方案1】:如果我的理解有误,请更新:
-
对于用户 ID 3,您已使用 TotalSalesAmount = 300*1 + 500*1 + 111*5(不包括用户 ID 5 的销售金额,而用户 ID 4 的子用户又为用户 ID 3 创建了销售金额)。所以 TotalSalesAmount
对于用户 ID 3,应计算为:300*1 + 500*1 +300*1 + 111*5 = 1655 而不是 1355。
如果我的上述理解是正确的,你可以通过使用公用表表达式的递归能力得到想要的结果,然后计算出运行总计:
-- create a common table expression to get OwnSaleAmount for logged in user and all the users who are added
由当前用户和更多。
with tblOwnSaleAmount as
(
select UM.UserId, UM.AddedBy, ( SM.Price*SP.Quantity ) as OwnSaleAmount
from UserMaster UM
join SalesMaster SM on SM.UserId = UM.UserId
join SalesProducts SP on SP.SaleId = SM.SalesId
where UM.UserId = 1 -- Userid of logged in user which will act as anchor member
-- for later subqueries
union all
select UM.UserId, UM.AddedBy, ( SM.Price*SP.Quantity ) as OwnSaleAmount
from UserMaster UM
join tblOwnSaleAmount on tblOwnSaleAmount.UserId = UM.AddedBy
join SalesMaster SM on SM.UserId = UM.UserId
join SalesProducts SP on SP.SaleId = SM.SalesId
)
select OSA.*
, TotalSalesAmount = isnull(
(
select sum( OSA1.OwnSaleAmount )
from tblOwnSaleAmount OSA1
where OSA1.AddedBy > = OSA.UserId
), 0 )
+ OSA.OwnSaleAmount
from tblOwnSaleAmount OSA
order by OSA.UserId
编辑:更新查询:
--1. Corrected joins in anchor query to fetch records for users who have no records in SalesMaster Table.
--2. IS it another requirement that user entries with status id = 2 should not be considered?
with tblOwnSaleAmount as
(
select UM.UserId, UM.AddedBy, sum( SM.Price*SP.Quantity ) as OwnSaleAmount
from UserMaster UM
left join SalesMaster SM on SM.UserId = UM.UserId -- Missed requirement1
left join SalesProducts SP on SP.SaleId = SM.SalesId -- Missed requirement1
where UM.UserId = 2 -- Userid of logged in user which will act as anchor member
group by UM.UserId ,UM.AddedBy -- for later subqueries
union all
select UM.UserId, UM.AddedBy, ( SM.Price*SP.Quantity ) as OwnSaleAmount
from UserMaster UM
join tblOwnSaleAmount on tblOwnSaleAmount.UserId = UM.AddedBy
join SalesMaster SM on SM.UserId = UM.UserId
join SalesProducts SP on SP.SaleId = SM.SalesId
),
tbldistinctOwnSaleAmount as
(
select distinct UserId, AddedBy, OwnSaleAmount
from tblOwnSaleAmount
) ,
tblTotalOwnSaleAmount as
(
select OSA.UserId,OSA.AddedBy, sum( OSA.OwnSaleAmount ) as OwnSaleAmount
from tbldistinctOwnSaleAmount OSA
group by OSA.UserId ,OSA.AddedBy
)
select OSA.*
, TotalSalesAmount = isnull(
(
select sum( OSA1.OwnSaleAmount )
from tblTotalOwnSaleAmount OSA1
where OSA1.UserId > OSA.UserId
), 0 )
+ OSA.OwnSaleAmount
from tblTotalOwnSaleAmount OSA
order by OSA.UserId
希望对你有帮助!!!
[EDIT2]:更新了遗漏要求 2 的查询:
--2. IS it another requirement that user entries with status id = 2 should not be considered? -- Yes!!!
with tblOwnSaleAmount as
(
select UM.UserId, UM.AddedBy, sum( SM.Price*SP.Quantity ) as OwnSaleAmount
from UserMaster UM
left join SalesMaster SM on SM.UserId = UM.UserId and SM.statusID = 1-- Missed requirement1 and 2
left join SalesProducts SP on SP.SaleId = SM.SalesId -- Missed requirement1
where UM.UserId = 2 -- Userid of logged in user which will act as anchor member
group by UM.UserId ,UM.AddedBy -- for later subqueries
union all
select UM.UserId, UM.AddedBy,
case when SM.statusID = 1 then ( SM.Price*SP.Quantity )
else 0 end as OwnSaleAmount --Missed Requirement 2.
from UserMaster UM
join tblOwnSaleAmount on tblOwnSaleAmount.UserId = UM.AddedBy
join SalesMaster SM on SM.UserId = UM.UserId
join SalesProducts SP on SP.SaleId = SM.SalesId
),
tbldistinctOwnSaleAmount as
(
select distinct UserId, AddedBy, OwnSaleAmount
from tblOwnSaleAmount
) ,
tblTotalOwnSaleAmount as
(
select OSA.UserId,OSA.AddedBy, sum( OSA.OwnSaleAmount ) as OwnSaleAmount
from tbldistinctOwnSaleAmount OSA
group by OSA.UserId ,OSA.AddedBy
)
select OSA.*
, TotalSalesAmount = isnull(
(
select sum( OSA1.OwnSaleAmount )
from tblTotalOwnSaleAmount OSA1
where OSA1.UserId > OSA.UserId
), 0 )
+ OSA.OwnSaleAmount
from tblTotalOwnSaleAmount OSA
order by OSA.UserId
要获得正确的结果,您需要更新锚表的 on 谓词,然后为进一步的递归表添加 case 语句。
【讨论】:
感谢您的宝贵反馈。它对我有用,除了我在查询中做了一点更改,我已将 Additionalby 更改为 UserId select OSA.* , TotalSalesAmount = isnull( ( select sum( OSA1.OwnSaleAmount ) from tblOwnSaleAmount OSA1 where OSA1.UserId > = OSA.UserId - -ctm), 0) 请查看... 如果登录用户在 SalesMaster 表中没有记录,则查询返回零结果。此外,如果 SalesMaster 表具有相同 UserID 的多个条目,那么结果也是不正确的。提前致谢。 嗨..刚刚看到您更新的要求。你还在寻找答案吗? 好吧,我必须对你的 SQL 技能说“脱帽致敬”。是的,我仍在寻找查询。你能回答***.com/revisions/19362433/2 根据您的要求更新查询。不应该考虑状态 id = 2 的用户条目是另一个要求吗?以上是关于根据角色类型来自 3 个表的分层数据的主要内容,如果未能解决你的问题,请参考以下文章
阶段3 1.Mybatis_09.Mybatis的多表操作_8 mybatis多对多操作-查询角色获取角色下所属用户信息