Update next record based on last updated record - sql

I'm struggling to find a solution to update the calculation in the same table based on last updated records order by select column.
I have tried LEAD & LAG, but can't give complete solution of my problem.
Here is my table:
ID PID QTY INVQTY **Desired Result** Calculation
1 1 2 112 110 (112 - 2)
2 1 2 112 108 (110 - 2)
3 1 1 112 107 (108 - 1)
4 1 1 112 106 (107 - 1)
5 1 4 112 102 (106 - 4)
6 1 2 112 100 (102 - 2)
7 1 12 112 88 (100 - 12)
8 1 5 112 83 (88 - 5)
9 2 1 2 1 (2 - 1)
10 2 2 2 -1 (1 - 2)
11 2 3 2 -4 (-1 - 3)
I tried below query but didn't succeed.
select *,
(LAG(a.invqty - a.Qty, 0) OVER (PARTITION BY a.pid ORDER BY a.id)) - (LAG(a.Qty, 1, 0) OVER (PARTITION BY a.pid ORDER BY a.id))
from #RunTotalTestData a
order by a.pid, a.id
I can use a while loop, but there are more than 50K records. I want to do it in the fastest possible way.

Hmmm . . . If you want a select, then you want a cumulative sum:
select rttd.*,
(invqty -
sum(qty) over (partition by pid order by id)
) as desired_result
from #RunTotalTestData rttd;
If you actually want an update (as the title to the question suggests), you can use this in an updatable CTE>

Related

Decreasing of the sum by percentage (subtraction of percentage) SQL

Substraction of percentage
I have got a table where is one record. Table looks like:
cust_code, SUM
1 25
I need to calculate a subtraction like this.
cust_code, ID, SUM
1 1 25
1 2 23
1 3 21.16
1 4 19.47
1 5 17.91
1 6 16.48
1 7 15.16
1 8 13.95
. . .
. . .
. . .
1 15 7.78
where value of sum in record 2 is subtracted by 8% of record 1,
value of sum in record 3 is subtracted by 8% of record 2,
value of sum in record 4 is subtracted by 8% of record 3, etc.
Max ID will be 15.
It should be single query, I can use any additional external table (containing for example simple counter from 0 to 15).
Best regards,
Volcano
Easy to do with a recursive CTE:
WITH cte AS
(SELECT cust_code, 1 AS id, sum FROM cust
UNION ALL
SELECT cust_code, id + 1, sum * 0.92 FROM cte WHERE id < 15)
SELECT * FROM cte ORDER BY id;
cust_code id sum
---------- ---------- ----------
1 1 25.0
1 2 23.0
1 3 21.16
1 4 19.4672
1 5 17.909824
1 6 16.4770380
1 7 15.1588750
1 8 13.9461650
1 9 12.8304718
1 10 11.8040340
1 11 10.8597113
1 12 9.99093444
1 13 9.19165969
1 14 8.45632691
1 15 7.77982076

T SQL Cumulative Subtraction

I'm using MS SQL Server.
I have the below table:
SKU Shop WeekNum ShopPrioirty Replen OpeningStock
111 100 1 1 10 5000
111 200 1 2 10 NULL
111 300 1 3 5 NULL
111 400 1 4 8 NULL
222 100 2 1 20 6000
222 200 2 2 15 NULL
222 300 2 3 12 NULL
222 400 2 4 10 NULL
This is the desired result:
SKU Shop WeekNum ShopPrioirty Replen OpeningStock
111 100 1 1 10 5000
111 200 1 2 10 4990
111 300 1 3 5 4980
111 400 1 4 8 4975
222 100 2 1 20 6000
222 200 2 2 15 5980
222 300 2 3 12 5965
222 400 2 4 10 5953
For a given week, a SKU exists in multiple shops and is assigned a priority. At Priority 1 the opening stock is assigned.
However, I need to update the Opening Stock (where it is currently NULL) to equal the previous Opening Stock Minus the Previous Replen.
Before I attempt the update, I tried to just do a SELECT
SELECT SKU
,Shop
,WeekNum
,StorePriority
,Replen
,OpeningStock
,OpeningStock - Replen OVER (ORDER BY SKU,Shop,WeekNum ROWS UNBOUNDED PRECEDING) AS Opening
FROM [table1] t
But I receive the error:Incorrect syntax near the keyword 'OVER'.
Is a running sum the correct way to go?
Would it be best to create a key made up from the SKU\Shop\WeekNum\Priority?
Thanks.
I've made a couple of assumptions here on your PARTITION BY and ORDER BY clauses, but this gets you the result you're after. As you only have a value for OpeningStock in the first row for a SKU, then I use FIRST_VALUE to get the First Value, and then take away all prior values of Replen:
WITH VTE AS(
SELECT *
FROM (VALUES(111,100,1,1,10,5000),
(111,200,1,2,10,NULL),
(111,300,1,3,5 ,NULL),
(111,400,1,4,8 ,NULL),
(222,100,2,1,20,6000),
(222,200,2,2,15,NULL),
(222,300,2,3,12,NULL),
(222,400,2,4,10,NULL))V(SKU,Shop,WeekNum,ShopPrioirty,Replen,OpeningStock))
SELECT V.SKU,
V.Shop,
V.WeekNum,
V.ShopPrioirty,
V.Replen,
V.OpeningStock,
FIRST_VALUE(V.OpeningStock) OVER (PARTITION BY V.SKU ORDER BY V.ShopPrioirty,V.WeekNum ROWS UNBOUNDED PRECEDING) -
ISNULL(SUM(V.Replen) OVER (PARTITION BY V.SKU ORDER BY V.ShopPrioirty,V.WeekNum ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0) AS CurrentStock
FROM VTE V;

sql for Access Database

I am dealing with a huge volume of traffic data. I want to identify the vehicles which have changed their lanes in MS Access database. I want to identify those records only which has changed the lane (immediate two records: before lane change and after lane change)
Traffic Data:
Vehicle_ID Lane_ID Frame_ID Distance
1 2 12 100
1 2 13 103
1 2 14 105
2 1 15 107
***2 1 16 130
2 2 17 135***
2 2 18 136
***3 1 19 140
3 2 20 141***
3 2 21 147
4 2 22 149
***4 2 23 151
4 1 24 154***
4 1 25 159
With assistance from here i have sorted out those Vehicle_ID which have changed their lanes:
SELECT t.Vehicle_ID, COUNT(t.Lane_ID) AS [Lane Count]
FROM (
SELECT DISTINCT Vehicle_ID, Lane_ID FROM Table1
) AS t
GROUP BY t.Vehicle_ID
HAVING COUNT(t.Lane_ID) > 1
Shown Result:
Vehicle_ID Lane Count
2 2
3 2
4 2
Now i want to do further analysis withe records of lane changing by segregating immediate two records: before and after lane change. My desired output would be:
Desired Result:
Vehicle_ID Lane_ID Frame_ID Distance
***2 1 16 130
2 2 17 135***
***3 1 19 140
3 2 20 141***
***4 2 23 151
4 1 24 154***
Assuming the frame ids have no gaps, you can do this using joins:
select t1.*
from (table1 as t1 inner join
table1 as t1prev
on t1prev.Vehicle_ID = t1.Vehicle_ID and
t1prev.frame_id = t1.frame_id - 1
) inner join
table1 as t1next
on t1next.Vehicle_ID = t1.Vehicle_ID and
t1next.frame_id = t1.frame_id + 1
where t1prev.lane_id <> t1.lane_id or
t1next.lane_id <> t1.lane_id;
Otherwise, this will be a very expensive query.
You can do it with EXISTS:
select t.* from Table1 t
where
exists (
select 1 from Table1
where
vehicle_id = t.vehicle_id
and
frame_id in (t.frame_id - 1, t.frame_id + 1)
and
lane_id <> t.lane_id
)

SQL. How to combine two records with the same ID into one line based on value's in a column

SQL Server 2012: how to combine two records with the same ID (TransportOrder) into one line based on value's in a column (PalletType)?
Example: order 678 has two lines with 1 europallet en 3 BetweenEuropallet. So de order takes only 1 TransportEuropalletPlace.
The output should be in the case of order 678, one line, telling there is total 4 europallets (sum 1 + 3 from two lines) and 1 TransportEuropalletPlace (SUM 1 + 0)
How to achieve this with SQL query?
Original output:
TransportOrder PalletType Quantity TransportEuropalletPlace
--------------------------------------------------------------------------
123 Minipallet 1 0.5
345 Europallet 1 1
678 Europallet 1 1
678 BetweenEuropallet 3 0
900 Europallet 2 2
Output needed for order 678:
TransportOrder PalletType Quantity TransportEuropalletPlace
--------------------------------------------------------------------------
123 Minipallet 1 0.5
345 Europallet 1 1
678 Europallet 4 1
900 Europallet 2 2
This should get you started:
SELECT
TransportOrder,
SUM(ISNULL(Europallet,0) + ISNULL(BetweenEuropallet, 0)) as 'Pallets'
FROM Table_Name
GROUP BY TransportOrder
You should group by the column TransportOrder, as in:
select
transportorder,
max(pallettype) as pallettype,
sum(quantity) as quantity,
sum(transporteuropalletplace) as transporteuropalletplace
from my_table
group by transportorder

Simple data, Complex query on SQL Server

I need to make a query over an SQL Server table but I don't know exactly how.
Consider this table (the real table is much more complex, Ord1 and Ord2 are dates that could be null, but i simplified it to this case):
Data of MyTable
ID MaqID Ord1 Ord2
------------------------
1 144 4 3
2 144 2 1
3 12 2 3
4 144 3 5
5 12 3 1
6 144 4 2
7 12 2 4
8 144 2 3
9 12 1 5
10 12 3 2
I need records for specific MaqID in Specific Order. I get that with this Query:
SELECT * FROM myTable WHERE MaqID=144 ORDER BY MaqID, Order1 DESC, Order2
Wich give me:
ID MaqID Ord1 Ord2
------------------------
6 144 4 2
1 144 4 3
4 144 3 5
2 144 2 1
8 144 2 3
Now, I need a single query that, for each MaqID, return the first ID for each subquery following above order. The result should be:
Expected result
MaqID ID
-----------
144 6
12 5
I have already try distinct conbination of TOP a MAX, but TOP result only one result and i need one for each MaqID, and for Max I have not field to maximize.
To sumarize: I need the first ID for each MaqID from a subquery in a specific order
Any ideas? Thanks!
You can do this using row_number():
select t.*
from (select t.*,
row_number() over (partition by macid Order1 DESC, Order2) as seqnum
from mytable t
) t
where seqnum = 1;