Sql 将计算值分布到多行
我有两张桌子Sql 将计算值分布到多行,sql,sql-server,Sql,Sql Server,我有两张桌子 Table of projects ProjectID, SOP, IncomeA, IncomeB 1 2021-01 100.000 0 2 2022-11 5.000 2.000 列SOPOffset与列SOP的年份相关。因此,项目1在2021年和2022年有收入,而项目2在2022年、2023年和2024年有收入 现有查询的结果是 year income 2021 1.000 -- #1 offset
Table of projects
ProjectID, SOP, IncomeA, IncomeB
1 2021-01 100.000 0
2 2022-11 5.000 2.000
列SOPOffset
与列SOP
的年份相关。因此,项目1在2021年和2022年有收入,而项目2在2022年、2023年和2024年有收入
现有查询的结果是
year income
2021 1.000 -- #1 offset 0
2022 3.000 -- #1 offset 1 + #2 offset 0
2023 500 -- #2 offset 1
2024 500 -- #2 offset 2
一项新的要求是,IncomeA
和IncomeB
这两个列需要在每个项目中最多分配3年。这意味着项目1和项目2的SOPOffset将分别为2021年和2022年增加50.000和s,而项目2和项目3的SOPOffset将分别为2022年和2023年增加2333.34和2024年增加2333.33
year income
2021 51.000 -- #1 offset 0 + (100.000 + 0)/2
2022 55.333,34 -- #1 offset 1 + #2 offset 0 + (100.000 + 0)/2 + 7000/3 (rounded up to 2333,34)
2023 2,833,34 -- #2 offset 1 + 7000/3 (rounded down to 2333,33)
2024 2,833,34 -- #2 offset 2 + 7000/3 (rounded down to 2333,33)
这个新的需求是否可以在单个查询中实现?我当前的解决方案是在应用程序代码本身中实现的,或者在SQL中使用循环等
编辑03.08.2020 15:30
根据注释中的要求,这是现有的查询,它使用稍微不同的表结构和一些附加信息来构建完整的结果集
SELECT
YEAR(cp.datSOP) + pv.intYearOffset,
SUM(pv.decPrice / cr.decRate * pv.intVolume) as IntakeEUR
FROM
tblProjectVolume pv
INNER JOIN tblProject sp ON sp.intProjectId = pv.intProjectId
INNER JOIN tblCustomerProject cp ON cp.intCustomerProjectId = sp.intCustomerProjectId AND (YEAR(cp.datSOP) + pv.intYearOffset >= 2019)
INNER JOIN tblCurrency c ON c.intCurrencyId = sp.intCurrencyId
INNER JOIN tblCurrencyRate cr ON cr.intCurrencyId = c.intCurrencyId AND cr.intYear = 2019
group by
YEAR(cp.datSOP) + pv.intYearOffset
order by
YEAR(cp.datSOP) + pv.intYearOffset
详细结果有一个附加的联接和分组依据
SELECT
YEAR(cp.datSOP) + pv.intYearOffset, bu.intBusinessDivisionId,
SUM(pv.decPrice / cr.decRate * pv.intVolume) as IntakeEUR
FROM
tblProjectVolume pv
INNER JOIN tblProject sp ON sp.intProjectId = pv.intProjectId
INNER JOIN tblCustomerProject cp ON cp.intCustomerProjectId = sp.intCustomerProjectId AND (YEAR(cp.datSOP) + pv.intYearOffset >= 2019)
INNER JOIN tblCurrency c ON c.intCurrencyId = sp.intCurrencyId
INNER JOIN tblCurrencyRate cr ON cr.intCurrencyId = c.intCurrencyId AND cr.intYear = 2019
INNER JOIN tblProductMapping pm ON pm.intProductMappingId = sp.intProductMappingId
INNER JOIN tblBusinessUnit bu ON bu.intBusinessUnitId = pm.intBusinessUnitId
group by
YEAR(cp.datSOP) + pv.intYearOffset, bu.intBusinessDivisionId
order by
YEAR(cp.datSOP) + pv.intYearOffset, bu.intBusinessDivisionId
关键的一点是你需要按年数分配收入。首先,你需要找出年数。这是在CTEincome
中完成的,它使用count()
来确定每个项目的偏移量。一旦你有了它,就把总收入除以它
declare @projects table
(
ProjectID int,
SOP int,
IncomeA decimal(10,2),
IncomeB decimal(10,2)
)
declare @income table
(
ProjectID int,
SOPOffset int,
Income decimal(10,2)
)
insert into @projects
values (1, 2021, 100000, 0),
(2, 2022, 5000, 2000)
insert into @income
values (1, 0, 1000),
(1, 1, 2000),
(2, 0, 1000),
(2, 1, 500),
(2, 2, 500)
; with income as
(
select ProjectID, SOPOffset, Income,
TotalOffset = count(*) over (partition by ProjectID)
from @income
)
select year = (p.SOP + i.SOPOffset),
income = SUM( i.Income
+ ((p.IncomeA + p.IncomeB) / i.TotalOffset) )
from @projects p
inner join income i on p.ProjectID = i.ProjectID
group by (p.SOP + i.SOPOffset)
附言:在你发布你的实际查询之前,我提出了这个查询。我相信您将能够根据您的查询进行调整您可以显示您现有的查询吗?还请解释如何获得当前测试的结果query@Squirrel我已将其添加到该解决方案的初始POSTINGTANKS中,但这太容易了;)它忽略了两个要求:(a)将值分配到最多3年的时间;(b)在单个查询中。(a) 可通过IIF
在TotalOffset
计数处求解。但是(b)有点问题,我认为-而且不是,将带有收入的嵌入select语句的from
中不幸不是一个解决方案…我发布的解决方案只是一个查询。或者,在单个查询中,您所说的到底是什么意思?
?由于需求发生了变化,我可以使用您的解决方案,只需稍作更改(重新保护)。以前,查询必须在SQL和应用程序使用的DB框架中实现,该应用程序只能执行功能有限的单个查询。
declare @projects table
(
ProjectID int,
SOP int,
IncomeA decimal(10,2),
IncomeB decimal(10,2)
)
declare @income table
(
ProjectID int,
SOPOffset int,
Income decimal(10,2)
)
insert into @projects
values (1, 2021, 100000, 0),
(2, 2022, 5000, 2000)
insert into @income
values (1, 0, 1000),
(1, 1, 2000),
(2, 0, 1000),
(2, 1, 500),
(2, 2, 500)
; with income as
(
select ProjectID, SOPOffset, Income,
TotalOffset = count(*) over (partition by ProjectID)
from @income
)
select year = (p.SOP + i.SOPOffset),
income = SUM( i.Income
+ ((p.IncomeA + p.IncomeB) / i.TotalOffset) )
from @projects p
inner join income i on p.ProjectID = i.ProjectID
group by (p.SOP + i.SOPOffset)