Есть ли возможность создать PIVOT с постепенным вычитанием значений в отдельных столбцах? - PullRequest
1 голос
/ 25 марта 2019

Может кто-нибудь посоветовать мне, как создать PIVOT с некоторым расчетом?Простой PIVOT с «реальными данными» не проблема, но я понятия не имею, как включить некоторые вычисления, даже такие базовые, как, например, вычитание значений между некоторыми столбцами ...

Пожалуйста, если Вы будетекто-то может, попробуйте использовать пример таблиц и данных ниже ...

-- Structure
-- ---------

-- Table of Products
CREATE TABLE ListProducts
(
    ProductID INT IDENTITY(1,1) PRIMARY KEY,
    Name NVARCHAR(25)
);

-- Table of Processes
CREATE TABLE ListProcesses
(
    ProcessID INT IDENTITY(1,1) PRIMARY KEY,
    Name NVARCHAR(25)
);

-- DataTable
CREATE TABLE Production
(
    ProductionID INT IDENTITY(1,1) PRIMARY KEY,
    ProductID INT FOREIGN KEY REFERENCES ListProducts(ProductID),
    ProcessID INT FOREIGN KEY REFERENCES ListProcesses(ProcessID),
    Amount INT
);

-- Data
-- ----

INSERT INTO ListProducts(Name) VALUES ('Product1'),('Product2'),('Product3');

INSERT INTO ListProcesses(Name) VALUES ('Process1'),('Process2'),('Process3');

INSERT INTO Production(ProductID,ProcessID,Amount) VALUES
(1,1,25),(2,1,15),(3,1,20),(1,2,10),(2,2,10),(3,2,5),(1,3,5),(2,3,5);

Я хотел бы получить PIVOT как:

| Products | Process1 | Process2 | Process3 |
| Product1 |       15 |        5 |        5 |
| Product2 |        5 |        5 |        5 |
| Product3 |       15 |        5 |     NULL |

Как видите, вывод некак простой PIVOT, но у меня каждый «предыдущий» столбец вычитается из «следующего» столбца (кроме, конечно, последнего столбца) ...

Спасибо большое!:)

Ответы [ 3 ]

2 голосов
/ 25 марта 2019

Вы можете использовать условное агрегирование:

select lpr.name,
       sum(case when p.processid = 1 then p.amount when p.processid = 2 then -p.amount end) as process1,
       sum(case when p.processid = 2 then p.amount when p.processid = 3 then -p.amount end) as process2,
       sum(case when p.processid = 3 then p.amount end) as process3
from production p join
     listproducts lpr
     on p.productid = lpr.productid join
     listprocesses lpro
     on p.processid = lpro.processid
group by lpr.name;

Здесь - это дБ <> скрипка.

1 голос
/ 25 марта 2019

Вы можете попробовать ниже, используя функцию lead ()

DEMO

with cte as
(
select *,case when processname<>'process3' then 
amount-coalesce(lead(amount) over(partition by productname order by processname),0) else amount end as amt from 
(
select b.name as productname, c.name as processname,amount
from Production a
inner join ListProducts b on a.productid=b.ProductID
inner join ListProcesses c on a.ProcessID=c.ProcessID
)A
)

select productname, max(case when processname='Process1' then amt end) as process1,
max(case when processname='Process2' then amt end) process2,
max(case when processname='Process3' then amt end) process3
from cte 
group by productname

ВЫХОД:

productname process1    process2    process3
Product1    15            5           5
Product2    5             5           5
Product3    15            5 
1 голос
/ 25 марта 2019

Вы можете написать свой запрос следующим образом, используя PIVOT и LEAD.

select [name] as Products, Process1, Process2, Process3 
from   (select t1.Name, 
               t2.amount - Isnull((Lead(t2.amount) 
                                      over(partition by T2.productid 
                                        order by t2.processid ) ), 0) amount, 
               t3.Name as ProcesName 
        from   listproducts t1 
               inner join production t2 
                       ON t1.productid = t2.productid 
               inner join listprocesses t3 
                       ON t3.processid = t2.processid) t 
       pivot ( max(amount) 
             for procesname in ([Process1], 
                                [Process2], 
                                [Process3]) ) pvt 

Демонстрация онлайн

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