Previous and Next row record - sql-server

I have following output
ID Number Speed LAT LONG DATETIME
101 AB01 15 73.066016 33.5840768 9/1/15 23:10
101 AB01 20 73.0619712 33.5871456 9/1/15 23:30
101 AB01 0 73.0722176 33.6007488 9/1/15 23:45
101 AB01 0 73.0722112 33.6007488 9/2/15 02:10
101 AB01 0 73.0722176 33.6007008 9/2/15 02:35
101 AB01 0 73.0722432 33.6007456 9/2/15 04:35
101 AB01 0 73.0721664 33.6007904 9/3/15 12:35
101 AB01 0 73.072192 33.6007488 9/3/15 13:35
101 AB01 0 73.072192 33.6007488 9/4/15 11:35
101 AB01 0 73.072192 33.6007488 9/4/15 14:35
101 AB01 1 73.072192 33.6007488 9/5/15 14:35
but required output are
ID Number Speed LAT LONG DATETIME
101 AB01 15 73.066016 33.5840768 9/1/15 23:10
101 AB01 20 73.0619712 33.5871456 9/1/15 23:30
101 AB01 0 73.0722176 33.6007488 9/1/15 23:45
101 AB01 0 73.072192 33.6007488 9/4/15 14:35
101 AB01 1 73.072192 33.6007488 9/5/15 14:35
i want to skip extra 0 speed value.if i include these 0 zero's query response time increase.
code attempt
SELECT Distinct ID,Number,Speed,LAT,LONG,DATETIME
FROM table
group by D,Number,Speed,LAT,LONG,DATETIME

You can use LEAD, LAG window functions to detect speed discontinuities (if this is what you actually want):
SELECT ID, Number, Speed, LAT, [LONG], [DATETIME]
FROM (
SELECT ID, Number, Speed, LAT, [LONG], [DATETIME],
LEAD(Speed) OVER (PARTITION BY ID, Number
ORDER BY [DATETIME]) AS NextSpeed,
LAG(Speed) OVER (PARTITION BY ID, Number
ORDER BY [DATETIME]) AS PrevSpeed
FROM mytable) AS t
WHERE Speed <> COALESCE(NextSpeed, -1) OR Speed <> COALESCE(PrevSpeed, -1)
Demo here

Related

Subtract depletion And Limit for SUM

First I'm using AdventureWork2019 as a reference
I have a query where I'm joining 5 Tables
USE [AdventureWorks2019]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Alter PROCEDURE dbo.TestLocation
#UseDate DateTime
AS
BEGIN
SET NOCOUNT ON;
SELECT prodID
,SUM(PurchQty) AS TotalPurchase
,SUM(SalesQty) AS TotalSell
,StartDate
from (
SELECT DISTINCT WO.ProductID AS prodID
, StartDate
,WO.OrderQty AS PurchQty
,SOD.OrderQty AS SalesQty
FROM Sales.SalesOrderDetail SOD
LEFT JOIN Production.WorkOrderRouting WOR ON WOR.ProductID = SOD.ProductID
--LEFT JOIN Production.Location PL ON PL.LocationID = WOR.LocationID
--The above Join is the one for the locationID and it's working Fine
LEFT JOIN Production.WorkOrder WO ON WO.ProductID = SOD.ProductID
FULL OUTER JOIN Purchasing.PurchaseOrderDetail POD ON POD.ProductID = SOD.ProductID
WHERE StartDate = #UseDate
-- AND PL.LocationID >= 10
) Test3
Group by prodID,StartDate
order by prodID ASC, StartDate
END
GO
EXEC TestLocation '2011-07-02 00:00:00.000'
Output(sample):
prodID TotalPurc TotalSell StartDate
717 8 36 2011-07-02 00:00:00.000
730 9 47 2011-07-02 00:00:00.000
744 2 3 2011-07-02 00:00:00.000
747 12 21 2011-07-02 00:00:00.000
749 5 15 2011-07-02 00:00:00.000
761 16 138 2011-07-02 00:00:00.000
775 26 91 2011-07-02 00:00:00.000
777 12 78 2011-07-02 00:00:00.000
802 6 21 2011-07-02 00:00:00.000
804 40 60 2011-07-02 00:00:00.000
806 16 138 2011-07-02 00:00:00.000
807 24 23 2011-07-02 00:00:00.000
810 21 28 2011-07-02 00:00:00.000
811 6 21 2011-07-02 00:00:00.000
813 8 37 2011-07-02 00:00:00.000
817 21 28 2011-07-02 00:00:00.000
And another Table For LocationID (as a warehouse)
SELECT LocationID,CostRate,Availability
FROM Production.Location
WHERE LocationID >= 10
order by CostRate ASC
LocationID CostRate Availability
50 12.25 120.00
60 12.25 120.00
30 14.50 120.00
40 15.75 120.00
45 18.00 80.00
10 22.50 96.00
20 25.00 108.00
What I want to do is to take each LoactionId and ProdID and take TotalPurc to the location and decrement the quantity in the Availability column, each TotalSell will increment the Availability column. The max Availability quantity is 130.
If all locations have no Available quantity that is the Available is 0 for all locations then it will stop.
the above will work with the date specified as you can check the query and run it if you have
AdventureWork2019
simple output to check how I want the data to be:
prodID TotalPurc TotalSell StartDate
717 8 36 2011-07-02 00:00:00.000
730 9 47 2011-07-02 00:00:00.000
744 2 3 2011-07-02 00:00:00.000
747 12 21 2011-07-02 00:00:00.000
749 5 15 2011-07-02 00:00:00.000
LocationID CostRate Availability
50 12.25 120.00
60 12.25 120.00
30 14.50 120.00
40 15.75 120.00
45 18.00 80.00
10 22.50 96.00
20 25.00 108.00
Output :
prodID TotalPurc TotalSell StartDate LocationID Availability Remaining
717 8 36 2011-07-02 00:00:00.000 50 130 18
717 8 36 2011-07-02 00:00:00.000 60 130 8
717 8 36 2011-07-02 00:00:00.000 30 128 0
--what happened above is that I took the (120-8) = 112 then 112+36 = 148 we only can use 130 then the remaining is 18 then we took the next `LocationID` with the least Cost (120+18 = 138 we can use 130 so we took the 8) and used it in the next `LocationID`
730 9 47 2011-07-02 00:00:00.000 30 130 36
730 9 47 2011-07-02 00:00:00.000 40 130 26
730 9 47 2011-07-02 00:00:00.000 45 106 0
744 2 3 2011-07-02 00:00:00.000 45 107 0
747 12 21 2011-07-02 00:00:00.000 45 116 0
749 5 15 2011-07-02 00:00:00.000 45 126 0
--the above is the same as the first 3 rows we subtract and add to the availability
The other condition is that if all locations reached 0 or 130 then stop
How can I do that in SQL Server? I tried using CTE but didn't work well with me and tried the cursor which I think is the best for this kind of thing but didn't achieve anything.
Thank you in advance
Edit :
ALTER FUNCTION GetStockMovment
(
-- Add the parameters for the function here
#ForDate Datetime
)
RETURNS #Sums TABLE (
RemoveQTY Numeric(24, 7),
ADDQTY Numeric(24, 7)
)
AS
BEGIN
Declare #WoSum Numeric(24, 7),
#SODSUM Numeric(24, 7),
#WORSum Numeric(24, 7),
#PODSum Numeric(24, 7)
select #SODSUM = SUM(SOD.OrderQty) from Sales.SalesOrderDetail SOD
INNER JOIN Sales.SalesOrderHeader SOH ON SOD.SalesOrderID = SOH.SalesOrderID
where SOH.OrderDate = #ForDate
select #WoSum = sum(orderQty) from Production.WorkOrder
where StartDate = #ForDate
select #PODSum = sum(POD.OrderQty) from Purchasing.PurchaseOrderDetail POD
INNER JOIN Purchasing.PurchaseOrderHeader POH ON POD.PurchaseOrderID = POH.PurchaseOrderID
where POH.OrderDate = #ForDate
select #WoSum = sum(WO.OrderQty) from Production.WorkOrder WO
where WO.DueDate = #ForDate
INSERT INTO #Sums (RemoveQTY,ADDQTY)
SELECT isnull(#SODSUM,0) + isnull(#WORSum,0) , isnull(#PODSum,0) + isnull(#WoSum,0)
RETURN;
END;
GO
select * from dbo.GetStockMovment ('2014-05-26 00:00:00.000')
Output:
RemoveQTY ADDQTY
189.0000000 5334.0000000
You should use LAG or LEAD function.
https://learn.microsoft.com/en-us/sql/t-sql/functions/lead-transact-sql?view=sql-server-ver15
https://learn.microsoft.com/en-us/sql/t-sql/functions/lag-transact-sql?view=sql-server-ver15

How to pivot table with complex condition?

I have a table with sample data
ProID ProNum TranDate
12 123 2017-12-12 08:04:00.000
12 140 2017-12-12 08:15:00.000
12 290 2017-12-12 09:15:00.000
13 100 2017-12-12 09:15:00.000
13 200 2017-12-12 10:59:00.000
12 50 2017-12-13 06:04:00.000
12 250 2017-12-13 08:00:00.000
I want to calculator and then pivot table, sample I want value in each time zone, I must calculator in each period hour, max[hourNext] - max[hourPre]
ProCode TranDate [05-06] [06-07] [07-08] [08-09] [09-10]
12 2017/12/12 0 0 140 150 0
12 2017/12/13 50 0 200 0 0
13 2017/12/12 0 0 0 100 100
I see ref as sql server pivot : group by with dynamic columns. But the problem of me as calculator max[hourNext] - max[hourPre]. If the previous time zone value does not exist, it automatically rollback the previous time zone value.

How to bulk update the date column

I have a table with 10000 records.
Sample
Id Transaction_Id Contract_Id Contractor_Id ServiceDetail_Id ServiceMonth UnitsDelivered CreateDate
----------------------------------------------------------------------------------------------------------------------------
1 1 352 466 590 2016-03-01 203 2016-04-25 17:01:55.000
2 1 352 466 566 2016-03-01 200 2016-04-25 17:02:38.807
3 1 352 466 138 2016-04-13 20 2016-04-13 00:00:00.000
5 1 352 466 138 2016-04-14 21 2016-04-13 00:00:00.000
6 10011 40 460 68 2016-03-17 10 2016-04-25 17:20:13.413
7 10011 40 460 511 2016-03-17 15 2016-04-25 17:20:13.413
8 10011 40 460 1611 2016-03-17 20 2016-04-25 17:20:13.413
9 20011 352 466 2563 2016-02-05 10 2016-04-25 17:20:25.307
11 100 40 460 68 2016-03-17 10 2016-04-25 17:29:23.653
In this table I have servicemonth with different dates.
I want to update the servicemonth column to the existing months last date.
suppose if I have 2016-03-17 in the table, it should be updated to 2016-3-31
suppose if I have 2016-05-12 in the table, it should be updated to 2016-5-31
Can anyone suggest a single query to update this?
EOMONTH: Returns the last day of the month that contains the specified date, with an optional offset.
UPDATE ... SET servicemonth = EOMONTH(servicemonth)
Update servicemonth
set servicemonth = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
--replace getdate() with the date column for which you want the end day of the month

FIFO Stock Valuation Through CTE-Recursion

I have copied it from this site because it's been already closed but I needed it for further solution. thus, kindly help me out.....
Problem : it's calculating the closing stock valuation through FIFO of issue as a whole. but i need cost of issues into Price column in the same row it belongs to itself.
declare #Stock table (Item char(3) not null,[Date] datetime not null,TxnType varchar(3) not null,Qty int not null,Price decimal(10,2) null)
insert into #Stock(Item , [Date] , TxnType, Qty, Price) values
('ABC','20120401','IN', 200, 750.00),
('ABC','20120405','OUT', 100 ,null ),
('ABC','20120410','IN', 50, 700.00),
('ABC','20120416','IN', 75, 800.00),
('ABC','20120425','OUT', 175, null ),
('XYZ','20120402','IN', 150, 350.00),
('XYZ','20120408','OUT', 120 ,null ),
('XYZ','20120412','OUT', 10 ,null ),
('XYZ','20120424','IN', 90, 340.00);
;WITH OrderedIn as (
select *,ROW_NUMBER() OVER (PARTITION BY Item ORDER BY [DATE]) as rn
from #Stock
where TxnType = 'IN'
), RunningTotals as (
select Item,Qty,Price,Qty as Total,0 as PrevTotal,rn from OrderedIn where rn = 1
union all
select rt.Item,oi.Qty,oi.Price,rt.Total + oi.Qty,rt.Total,oi.rn
from
RunningTotals rt
inner join
OrderedIn oi
on
rt.Item = oi.Item and
rt.rn = oi.rn - 1
), TotalOut as (
select Item,SUM(Qty) as Qty from #Stock where TxnType='OUT' group by Item
)
select
rt.Item,SUM(CASE WHEN PrevTotal > out.Qty THEN rt.Qty ELSE rt.Total - out.Qty END * Price)
from
RunningTotals rt
inner join
TotalOut out
on
rt.Item = out.Item
where
rt.Total > out.Qty
group by rt.Item
The result is only Closing Stock as per FIFO Basis as below:
Item ClsStock
ABC 40000.00
XYZ 37600.00
But I need the followings Result from the same query:
Item Date TxnType OpnQty OpnRate OpnVal InnQty InnRate InnVal OutQty OutRate OutVal ClsQty ClsRate ClsVal
ABC 20120401 IN 200 750 150000 200 750.00 150000
ABC 20120405 OUT 200 750.00 150000 100 750 75000 100 750.00 75000
ABC 20120410 IN 100 750.00 75000 50 700 35000 150 733.33 110000
ABC 20120416 IN 150 733.33 110000 75 800 60000 225 755.56 170000
ABC 20120425 OUT 225 755.56 170000 175 742.86 130000 50 800.00 40000
Total 0 0.00 0 325 753.85 245000 275 745.45 205000 50 800.00 40000
XYZ 20120402 IN 150 350 52500 150 350.00 52500
XYZ 20120408 OUT 150 350.00 52500 120 350 42000 30 350.00 10500
XYZ 20120412 OUT 30 350.00 10500 10 350 3500 20 350.00 7000
XYZ 20120424 IN 20 350.00 7000 90 340 30600 110 341.82 37600
Total 0 0.00 0 240 346.25 83100 130 350 45500 110 341.82 37600
Grand Total 0 #DIV/0! 0 565 580.71 328100 405 618.52 250500 160 485.00 77600

how to get result from this data

I want to compute result from this table.
I want quantity 1 - quantity2 as another column in the table shown below.
this table has more such records
I am trying to query but not been able to get result.
select * from v order by is_active desc, transaction_id desc
PK_GUEST_ITEM_ID FK_GUEST_ID QUANTITY TRANSACTION_ID IS_ACTIVE
---------------- -------------------- ---------------------- -------------------- -----------
12963 559 82000 795 1
12988 559 79000 794 0
12987 559 76000 793 0
12986 559 73000 792 0
12985 559 70000 791 0
12984 559 67000 790 0
12983 559 64000 789 0
12982 559 61000 788 0
12981 559 58000 787 0
12980 559 55000 786 0
12979 559 52000 785 0
12978 559 49000 784 0
12977 559 46000 783 0
12976 559 43000 782 0
I want another column that will contain the subtraction of two quantities .
DESIRED RESULT SHOULD BE SOMETHING LIKE THIS
PK_GUEST_ITEM_ID FK_GUEST_ID QUANTITY Result TRANSACTION_ID IS_ACTIVE
---------------- -------------------- ---------------------- -------------------- -----------
12963 559 82000 3000 795 1
12988 559 79000 3000 794 0
12987 559 76000 3000 793 0
12986 559 73000 3000 792 0
12985 559 70000 3000 791 0
12984 559 67000 3000 790 0
12983 559 64000 3000 789 0
12982 559 61000 3000 788 0
12981 559 58000 3000 787 0
12980 559 55000 3000 786 0
12979 559 52000 3000 785 0
12978 559 49000 3000 784 0
12977 559 46000 3000 783 0
12976 559 43000 NULL 782 0
to get the next lower transaction id you can use a subquery
Select max(transactionid)
from vinner
where vinner.tr.ansactionid <vouter.transactionid
This works fine for me:
select v1.transactionid as HigherTransactionID
,v2.transactionid as LowerTransactionId
,v1.quantity as HigherQuan
,v2.quantity as LowerQuan
,v1.quantity - v2.quantity as Result
from v as v1
left join v as v2 on
v2.transactionid =
(Select MAX(v.transactionid)
from v
where v.transactionid < v1.transactionid)
Tested with following Table:
quantity transactionid
8200 795
7900 794
6600 793
6300 792
6000 788
5700 787
4300 786
With following result:
HigherTransactionID LowerTransactionId HigherQuan LowerQuan Result
795 794 8200 7900 300
794 793 7900 6600 1300
793 792 6600 6300 300
792 788 6300 6000 300
788 787 6000 5700 300
787 786 5700 4300 1400
786 NULL 4300 NULL NULL
Hope this is what you expected
Try something like this:
SELECT
v1.*,
v1.QUANTITY - v2.QUANTITY AS result
FROM
v AS v1
-- always join transaction (some will be NULL in result)
LEFT JOIN
v AS v2
ON
-- join to lower trans id
v2.PK_TRANSACTION_ID = v1.PK_TRANSACTION_ID-1
WHERE
-- get only odd trans ids
v1.PK_TRANSACTION_ID % 2 = 1
ORDER BY
is_active DESC,
transaction_id DESC
But i am afraid it won't be deamon of speed :(.
select order2.Quantity-order1.Quantity,order1.fk_guestId, ...from v order1
join v order2 on order1.Transaction_id=order2.transaction_id+1
by is_active desc, transaction_id desc

Resources