Reputation: 485
I have a set of supply operation organised like this:
op_type | time_stamp | product | in | out
----------------------------------------------------
01 | 08:00:00 | p1 | 50 | 0
02 | 08:01:00 | p1 | 0 | 10
02 | 08:02:00 | p1 | 0 | 35
03 | 08:03:00 | p1 | 0 | 5
01 | 08:04:00 | p1 | 60 | 0
02 | 08:09:00 | p1 | 0 | 15
01 | 08:10:00 | p1 | 30 | 0
02 | 08:11:00 | p1 | 0 | 20
01 | 08:00:00 | p2 | 100 | 0
02 | 08:01:00 | p2 | 0 | 20
02 | 08:02:00 | p2 | 0 | 45
03 | 08:03:00 | p2 | 0 | 15
01 | 08:03:10 | p2 | 60 | 0
01 | 08:04:00 | p2 | 5 | 0
02 | 08:09:00 | p2 | 0 | 30
01 | 08:10:00 | p2 | 30 | 0
02 | 08:11:00 | p2 | 0 | 10
What I want is to select the list witch the SUM(in) group by product
will cover the SUM(out) group by product
starting from a given time
EX: for time_stamp>'08:05:00'
I have :
SUM(out) for p1=35
so the sum
and SUM(out) for p2=40
so the list I want to get would be
op_type | time_stamp | product | in | out
----------------------------------------------------
01 | 08:04:00 | p1 | 60 | 0
02 | 08:09:00 | p1 | 0 | 15
01 | 08:10:00 | p1 | 30 | 0
02 | 08:11:00 | p1 | 0 | 20
01 | 08:03:10 | p2 | 60 | 0
01 | 08:04:00 | p2 | 5 | 0
02 | 08:09:00 | p2 | 0 | 30
01 | 08:10:00 | p2 | 30 | 0
02 | 08:11:00 | p2 | 0 | 10
what i did is that i added tow column to the result witch one has the sum of out
and the other has the cumulative sum of in
SELECT B.*,C.sum_out FROM (SELECT A.*,SUM(in) OVER (PARTITION BY product ORDER BY time_stamp desc) AS sum_in FROM table A) B
LEFT OUTER JOIN
SELECT C.* FROM (SELECT product,SUM(out) AS sum_out from table GROUP BY product WHERE time_stamp>'08:05:00') C
ON B.product=C.product
so I get :
op_type | time_stamp | product | in | out | sum_in | sum_out
-------------------------------------------------------------------------
01 | 08:00:00 | p1 | 50 | 0 | 140 | 35
02 | 08:01:00 | p1 | 0 | 10 | 90 | 35
02 | 08:02:00 | p1 | 0 | 35 | 90 | 35
03 | 08:03:00 | p1 | 0 | 5 | 90 | 35
01 | 08:04:00 | p1 | 60 | 0 | 90 | 35
02 | 08:09:00 | p1 | 0 | 15 | 30 | 35
01 | 08:10:00 | p1 | 30 | 0 | 30 | 35
02 | 08:11:00 | p1 | 0 | 20 | 0 | 35
01 | 08:00:00 | p2 | 100 | 0 | 195 | 40
02 | 08:01:00 | p2 | 0 | 20 | 95 | 40
02 | 08:02:00 | p2 | 0 | 45 | 95 | 40
03 | 08:03:00 | p2 | 0 | 15 | 95 | 40
01 | 08:03:10 | p2 | 60 | 0 | 95 | 40
01 | 08:04:00 | p2 | 5 | 0 | 35 | 40
02 | 08:09:00 | p2 | 0 | 30 | 30 | 40
01 | 08:10:00 | p2 | 30 | 0 | 30 | 40
02 | 08:11:00 | p2 | 0 | 10 | 0 | 40
If I add the clause WHERE B.sum_in<=C.sum_out
i would be able to get
op_type | time_stamp | product | in | out | sum_in | sum_out
-------------------------------------------------------------------------
02 | 08:09:00 | p1 | 0 | 15 | 30 | 35
01 | 08:10:00 | p1 | 30 | 0 | 30 | 35
02 | 08:11:00 | p1 | 0 | 20 | 0 | 35
01 | 08:04:00 | p2 | 5 | 0 | 35 | 40
02 | 08:09:00 | p2 | 0 | 30 | 30 | 40
01 | 08:10:00 | p2 | 30 | 0 | 30 | 40
02 | 08:11:00 | p2 | 0 | 10 | 0 | 40
So I will need one more row for each product.
Any idea how to perform this?? PS: I'm using SQL SERVER 2012.
Upvotes: 0
Views: 67
Reputation: 190
I drafted a possible solution, you can use subqueries to get all the accumulated transactions
Select time_stamp,
(Select Sum(SQ.InEntry - SQ.OutEntry) from Table_1 AS SQ where T.time_stamp > SQ.time_stamp AND T.product = SQ.product group by product) +
InEntry - OutEntry
, T.InEntry
, T.OutEntry
, product
from Table_1 T
order by product,time_stamp
To generate random data I used this statement
declare @FromDate date = '2016-01-01'
declare @ToDate date = '2016-12-31'
declare @product varchar(50)
set @product = ( select top 1 A.Prod from (Select 'A' AS Prod union all select 'B' AS Prod union all select 'C' AS Prod) AS A order by newid())
INSERT INTO [dbo].[Table_1]
([time_stamp]
,[product]
,[InEntry]
,[OutEntry])
Select
dateadd(day,
rand(checksum(newid()))*(1+datediff(day, @FromDate, @ToDate)),
@FromDate)
,@product
,0
,ABS(Checksum(NewID()) % 100)
INSERT INTO [dbo].[Table_1]
([time_stamp]
,[product]
,[InEntry]
,[OutEntry])
Select
dateadd(day,
rand(checksum(newid()))*(1+datediff(day, @FromDate, @ToDate)),
@FromDate)
,@product
,@product ,ABS(Checksum(NewID()) % 100)
,0
GO 40
Upvotes: 2
Reputation: 1917
You don't seem to be grouping by product? Anyway this may help, you can do your normal aggregates using SUM & GROUP BY grouping on what ever with the appropriate WHERE clause on the time.
But to get what you ask...
SUM(in) group by product will cover the SUM(out)
....you can use HAVING.....
Eg
SELECT Field1, Field2, SUM(IN), SUM(OUT)
FROM Table
WHERE Your_where_clause
GROUP BY Field1, Field2
HAVING SUM(IN) >= SUM(OUT)
Upvotes: 0