Распределить вычисленное значение по нескольким строкам - PullRequest
0 голосов
/ 03 августа 2020

У меня есть две таблицы

Table of projects

ProjectID, SOP,     IncomeA, IncomeB
1          2021-01  100.000      0
2          2022-11    5.000  2.000
Table of income per year per project

ProjectID, SOPOffset, Price, Volumn
1          0          10     1.000
1          1          10     2.000
2          0          15     1.000
2          1          20       500
2          2          20       500

Столбец 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 s добавит 50.000 к 2021 и 2022 годам, а проект 2 с 3 SOPOffset s добавит 2333,34 к 2022 году и 2333,33 к 2023 и 2024 годам

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)

Возможно ли это новое требование в одном запросе? Мое текущее решение реализовано в самом коде приложения или с использованием циклов, et c in SQL.

Edit 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

1 Ответ

0 голосов
/ 03 августа 2020

Ключевым моментом является то, что вам необходимо распределить доход по годам. Для начала нужно узнать количество лет. Это делается в CTE income, он использует 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)

PS: Я придумал запрос до того, как вы разместили свой фактический запрос. Я уверен, что вы сможете адаптировать это в соответствии с вашим запросом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...