Updating SQL Server based on unique row using WHILE LOOP - sql

I'm trying to update my table using WHILE LOOP, unfortunately, instead of updating it based on employeeidno, it gathers all the total aremployee in all employeeidno and then update the row of all employeeidno based on it.
Is there a way to segregate the SET #aremployee based on employeeidno?
What I basically what for this query is that for every WHILE LOOP it will capture the data gathered, and then add it to the next loop, but is based on employeeidno.
DECLARE #cnt INT = 0;
DECLARE #aremployee FLOAT = 0;
WHILE #cnt <= (SELECT TOP 1 RIGHT(accountcode,2) FROM accounting_tblearningsamendmentaccount_db WHERE LEFT(accountcode,2) = '02' AND approvedby IS NOT NULL ORDER BY accountcode DESC)
BEGIN
SET #cnt = #cnt + 1;
UPDATE accounting_tblpayroll_db
SET #aremployee = #aremployee + x.aremployee,
accounting_tblpayroll_db.aremployee = #aremployee
FROM (SELECT
MAX(RTRIM(LTRIM(employeeidno))) AS 'employeeidno',
SUM(debit) AS 'aremployee',
MAX(accountcode) as 'accountcode',
MAX(RTRIM(LTRIM(referenceno))) AS 'referenceno',
MAX(RTRIM(LTRIM(particulars))) AS 'particulars',
MAX(RTRIM(LTRIM(postedby))) AS 'postedby',
MAX(RTRIM(LTRIM(approvedby))) AS 'approvedby',
MAX(RTRIM(LTRIM(notedby))) AS 'notedby'
FROM accounting_tblearningsamendment_db WHERE LEFT(accountcode,2) = LEFT('02000',2)
AND accountcode != '02001' AND accountcode != '02002'
AND payrolldue is null AND datedue BETWEEN '2020-10-06' AND '2020-10-20'
AND accountcode = CONCAT('020', CONCAT(CASE WHEN #cnt < 10 THEN '0' ELSE '' END , #cnt))
GROUP BY employeeidno) AS x
WHERE x.employeeidno = accounting_tblpayroll_db.employeeidno
AND x.aremployee <
(((accounting_tblpayroll_db.cutoffpay + accounting_tblpayroll_db.leave + accounting_tblpayroll_db.nightdifferential + accounting_tblpayroll_db.regularholiday + accounting_tblpayroll_db.specialholiday + accounting_tblpayroll_db.additionalincome + accounting_tblpayroll_db.overtime
+ accounting_tblpayroll_db.apemployee + accounting_tblpayroll_db.thmonth + accounting_tblpayroll_db.christmasbonus + accounting_tblpayroll_db.administrativeallowance + accounting_tblpayroll_db.supervisoryallowance
+ accounting_tblpayroll_db.hazardallowance + accounting_tblpayroll_db.shortageallowance + accounting_tblpayroll_db.licenseallowance + accounting_tblpayroll_db.transportationallowance + loyaltyincentiveallowance - '1000.00'
)
- (accounting_tblpayroll_db.sss_ee + accounting_tblpayroll_db.med_ee + accounting_tblpayroll_db.pagibig_ee + accounting_tblpayroll_db.late + accounting_tblpayroll_db.undertime)))
AND accounting_tblpayroll_db.datefrom = '2020-10-06'
AND accounting_tblpayroll_db.dateto = '2020-10-20';
END;
Thank you in advance.
Edit:
This is the simplified version:
DROP TABLE #temtable1;
DROP TABLE #temtable2;
CREATE TABLE #temtable1
(
referenceno int,
employeeid varchar(10),
ccode varchar(10),
amount float(10)
);
INSERT INTO #temtable1
(referenceno,employeeid,ccode,amount)
VALUES('1001','2001','3001','11000.00');
INSERT INTO #temtable1
(referenceno,employeeid,ccode,amount)
VALUES('1003','2002','3002','11000.00');
INSERT INTO #temtable1
(referenceno,employeeid,ccode,amount)
VALUES('1005','2003','3003','11000.00');
INSERT INTO #temtable1
(referenceno,employeeid,ccode,amount)
VALUES('1001','2001','3004','10000.00');
INSERT INTO #temtable1
(referenceno,employeeid,ccode,amount)
VALUES('1003','2002','3005','10000.00');
INSERT INTO #temtable1
(referenceno,employeeid,ccode,amount)
VALUES('1005','2003','3006','10000.00');
CREATE TABLE #temtable2
(
referenceno int,
employeeid varchar(10),
total float(10)
);
INSERT INTO #temtable2
(referenceno,employeeid,total)
VALUES('1001','2001',NULL);
INSERT INTO #temtable2
(referenceno,employeeid,total)
VALUES('1002','2002',NULL);
INSERT INTO #temtable2
(referenceno,employeeid,total)
VALUES('1003','2003',NULL);
DECLARE #cnt INT = 0;
DECLARE #total INT = 0;
WHILE #cnt <= 10
BEGIN
SET #cnt = #cnt + 1;
UPDATE #temtable2
SET #total = #total + x1.amount,
total = #total
FROM(SELECT
MAX(referenceno) as referenceno,
MAX(employeeid) as employeeid,
ccode as ccode,
SUM(amount) as amount
FROM #temtable1
WHERE
ccode = CONCAT('30', CONCAT(CASE WHEN #cnt < 10 THEN '0' ELSE '' END , #cnt))
GROUP BY
employeeid,ccode) AS x1
WHERE x1.employeeid = #temtable2.employeeid
AND x1.amount < 25000
END
select * from #temtable2
Current Result:
Expected Result:
What I intend for this is that the query will loop and add all code that starts with 3, depending on what employeeid the data is under.
The query will the first loop starting 3001, then up to 3010, and add it consecutively until it will not exceed 25000, but it's on every employeeid.

Related

Returning last result set from stored procedure

Stored procedure a is calling another procedure b and b has two out parameter and also a result set with select statement. Now I want to return result set from a with select statement but when I execute a it shows two result sets, first from b and then from a.
So how to get result set of just a? Please I don't want to store result of b into temp table. thanks.
a usp_Save_IssuancePcsStToSt
b usp_Stitcher_Stock_Form
details of b
#st_code smallint,
#QltyCode varchar(30),
#ColorCode varchar(6),
#NetPieces int = NULL out ,
#NetWeight numeric(13,4) = NULL out
)
AS
BEGIN
DECLARE #rowNum int= 0;
SELECT
#rowNum = ROW_NUMBER() OVER (ORDER BY st_code, quality_code, o_color_code),
#NetPieces = ISNULL(SUM((rec_pcs + adj_plus_pcs + reopen_pcs)- (issued_pcs + adj_minus_pcs + re_packing_pcs+ return_pcs)), 0),
#NetWeight = ISNULL(SUM((rec_wt + adj_plus_wt + reopen_wt) - (issued_wt + adj_minus_wt + return_wt + re_packing_wt)), 0.00)
FROM
dbo.v_rpt_cc_transaction_all
WHERE
doc_date >= '03/02/2014'
AND st_code = #st_code
AND quality_code = #QltyCode
AND o_color_code = #ColorCode
GROUP BY
st_code, quality_code, o_color_code
SELECT #rowNum AS SerialNumber, ISNULL(#NetPieces, 0) AS net_pcs , ISNULL(#NetWeight, 0.00) AS net_wt

Rewrite SQL without cursor for Data Warehouse

I have SQL code (main core) below that works fine on SQL Server. How to rewrite it for T-SQL Azure SQL DW, which doesn't like cursor? I didn't find appropriate example and can't do it myself.
CREATE PROCEDURE calc_balance
CREATE TABLE output_table (Amount FLOAT, ValueStart FLOAT, ValueStop FLOAT);
DECLARE cursor_1 CURSOR FOR
SELECT Criteria, Amount, ValueStart, ValueStop
FROM Input_table
OPEN cursor_1
WHILE #fetchstatus = 0
BEGIN
FETCH NEXT FROM cursor_1 INTO #Criteria, #Amount, #ValueStart, #ValueStop;
#ValueStart1 = #balance;
#ValueStop1 = #ValueStart1 + #Amount;
IF (#Criteria = 1) AND (#balance> -100)
BEGIN
#Amount = 0;
#ValueStop1 = #ValueStart;
END;
#balance = #balance + #Amount + #ValueStart;
INSERT INTO output_table
VALUES (#Amount, #ValueStart1, #ValueStop1);
END;
You may want to try this.
with cte as (
select 0 as ctr, 0 as balance, Criteria, Amount, ValueStart, ValueStop, (select count(1) from Input_table) as ct from Input_table
union all
select ctr +1, balance + case when Criteria = 1 and balance >-100 then 0 else Amount end + ValueStart
, Criteria, Amount, balance
, case when Criteria = 1 and balance >-100 then balance + Amount else ValueStart end
, ct
from cte
where ctr < ct
)
Insert into output_table VALUES
(select Amount,ValueStart, ValueStop from cte where ctr>0)

Grouping within a While Loop, SQL Server

I've been building a while loop to populate a lot of data, and I'm struggling with grouping within the query - I want to add a group on Membership_Level but each time it is returning identical values (the total) for each Level.
Can anyone help me?
Thank you in advance!!!
DECLARE #Counter int
DECLARE #NumPerson int
SET #Counter = 1
WHILE #Counter <= 12
BEGIN
SET #NumPerson = (SELECT
SUM(Amount)
FROM [NewMember]
WHERE LEFT([PERIOD], 4) = 2016
AND GRADE_STATUS = 'N'
AND RIGHT([Period], 2) = #Counter)
SELECT
*
FROM (SELECT
CAST(#NumPerson AS varchar(6)) AS 'Number',
CASE
WHEN LEN(CAST(#Counter AS varchar(2))) = 1 THEN '0' + CAST(#Counter AS varchar(2))
ELSE CAST(#Counter AS varchar(2))
END AS 'Month') s
JOIN (SELECT
MAX('1') AS NGroup,
[PERIOD],
RIGHT([Period], 2) AS 'Month',
MEMBERSHIP_LEVEL
FROM [NewMember]
WHERE LEFT([PERIOD], 4) = 2016
AND GRADE_STATUS = 'N'
GROUP BY [MEMBERSHIP_LEVEL],
[PERIOD],
RIGHT([Period], 2)) t
ON s.[Month] = t.[Month]
SET #Counter = #Counter + 1
END

MSSQL After Insert Trigger not executing after database restore

I restored a SQL 2k5 Database to a SQL 2014 server (Note this is a SQL Web Edition instance) and it does not seem to execute at all.
CREATE TRIGGER [dbo].[tInsertTransactionsSnapshot]
ON [GDL_TNA].[dbo].[TRANSACTIONS]
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #FirstRecord int
DECLARE #LastRecord int
DECLARE #MSTSQ int
DECLARE #EventDate varchar(50)
SET #FirstRecord = (SELECT TOP 1 T_ID FROM INSERTED ORDER BY T_ID ASC)
SET #LastRecord = (SELECT TOP 1 T_ID FROM INSERTED ORDER BY T_ID DESC)
insert into GDL_TNA.dbo.dbg(Dbgfirst,dbgLast) VALUES (#FirstRecord,#LastRecord)
WHILE #FirstRecord <= #LastRecord
BEGIN
SET #MSTSQ = (SELECT MST_SQ FROM INSERTED WHERE T_ID = #FirstRecord)
SET #EventDate = (SELECT T_Date FROM INSERTED WHERE T_ID = #FirstRecord)
IF EXISTS(SELECT NULL FROM GDL_TNA.dbo.SNAPSHOTs WHERE MST_SQ = #MSTSQ AND SS_EVENT_DATE = #EventDate AND SS_ACTIVE = 1 AND SS_TYPE = 'TRANSACTION')
BEGIN
UPDATE GDL_TNA.dbo.SNAPSHOTs SET SS_ACTIVE = 0 WHERE MST_SQ = #MSTSQ AND SS_EVENT_DATE = #EventDate AND SS_ACTIVE = 1 AND SS_TYPE = 'TRANSACTION'
END
INSERT INTO GDL_TNA.dbo.SNAPSHOTs
(
[SS_TYPE]
,[SS_EVENT]
,[MST_SQ]
,[MD_ACTIVE]
,[MST_FIRST_NAME]
,[MST_LAST_NAME]
,[MD_SHIFTSTART]
,[MD_SHIFTEND]
,[COMP_ID]
,[DEPT_ID]
,[FUNC_ID]
,[MST_PREVIOUS_FIRST_NAME]
,[MST_PREVIOUS_LAST_NAME]
,[MST_RATE_NORMAL]
,[MST_RATE_TIMEANDHALF]
,[MST_RATE_DOUBLE]
,[MST_RATE_SPECIAL]
,[SS_EVENT_ID]
,[SS_EVENT_DATE]
,[SS_EVENT_START]
,[SS_EVENT_END]
,[SS_EVENT_APPROVED]
,[SS_EVENT_RATETYPE]
)
SELECT
'TRANSACTION'
,'INSERT'
,MST_SQ
,MD_ACTIVE
,MST_FIRST_NAME
,MST_LAST_NAME
,MD_SHIFTSTART
,MD_SHIFTEND
,COMP_ID
,DEPT_ID
,FUNC_ID
,MST_PREVIOUS_FIRST_NAME
,MST_PREVIOUS_LAST_NAME
,MST_RATE_NORMAL
,MST_RATE_TIMEANDHALF
,MST_RATE_DOUBLE
,MST_RATE_SPECIAL
,(
SELECT T_ID
FROM INSERTED
WHERE T_ID = #FirstRecord
)
,(
SELECT T_Date
FROM INSERTED
WHERE T_ID = #FirstRecord
)
,ISNULL((
SELECT
CASE
WHEN len(T_TIMEIN) = 6 THEN left(T_TIMEIN,2) + ':' + right(left(T_TIMEIN,4),2) + ':' + right(T_TIMEIN,2) + '.000'
WHEN len(T_TIMEIN) < 6 THEN '0'+left(T_TIMEIN,1) + ':' + right(left(T_TIMEIN,3),2) + ':' + right(T_TIMEIN,2) + '.000'
END
FROM INSERTED
WHERE T_ID = #FirstRecord
),'00:00:00.000')
,ISNULL((
SELECT
CASE
WHEN len(T_TIMEOUT) = 6 THEN left(T_TIMEOUT,2) + ':' + right(left(T_TIMEOUT,4),2) + ':' + right(T_TIMEOUT,2) + '.000'
WHEN len(T_TIMEOUT) < 6 THEN '0'+left(T_TIMEOUT,1) + ':' + right(left(T_TIMEOUT,3),2) + ':' + right(T_TIMEOUT,2) + '.000'
END
FROM INSERTED
WHERE T_ID = #FirstRecord
),'00:00:00.000')
,1
,1
FROM GDL_TNA.dbo.MASTER_DETAILS
WHERE MST_SQ = #MSTSQ
SET #FirstRecord = #FirstRecord + 1
END
END
Steps I have Taken
Check Trigger Status: SELECT name, is_disabled FROM sys.triggers (All Enabled)
Drop & Recreate Triggers on 2014 instance
Ran a Recompile of table with sp_recompile
Any advice would be greatly appreciated.

How to implement FIFO in sql

I working on FIFO implementation in sql.
I have Batch number concept in my application.
If suppose I am selling on inventory then my application should tell me that which inventory is the first come.
Lets. Say I purchased Inventory 'A' on 4th-Aug, 5th-Aug & 6th-Aug
On 4th Aug - A Inventory has batch number BT002 - 10 (Qty)
On 5th Aug - A's Inventory has batch number BT003 - 15 (Qty)
On 6th Aug - A's Inventory has batch number BT001 - 10 (Qty)
So, Now I am having stock Now in my hand as following :
A Inventory
BT002 - 10 - 4-Aug
BT003 - 15 - 5-Aug
BT001 - 10 - 6-Aug
Now If I want to sell that Inventory to anybody then my application should tell me that I should sell
BT002 (Batch number) inventory first beacause it came first.
That was the concept I am using in my application.
Now I want to sell 15 Qty from 'A' (Inventory).
Then O/p Should be like this :
BT002 - 10
BT003 - 5
Here's My Query :
SELECT ISNULL(SUM(qty),0) AS Qty,batch_no,accept_date FROM RS_GIN_Master
GROUP BY batch_no,accept_date
HAVING ISNULL(SUM(qty),0) <= 15
ORDER BY accept_date asc
O/p Of Given Query :
How can I get O/P like this :
BT002 - 10
BT003 - 5
Any Help will be appreciated.
Thank you in Advance.
This should work for you:
Working sample on Fiddle
CREATE FUNCTION [dbo].[GetBatchAmounts]
(
#requestedAmount int
)
RETURNS
#tBatchResults TABLE
(
Batch nvarchar(50),
Amount int
)
AS
BEGIN
/*This is just a mock of ersults of your query*/
DECLARE #RS_GIN_Master TABLE(
Qty int,
batch_no NVARCHAR(max),
accept_date DATETIME
)
insert into #RS_GIN_Master(Qty,batch_no,accept_date)
SELECT 10,'BT002', CAST(CAST(2014 AS varchar) + '-' + CAST(8 AS varchar) + '-' + CAST(4 AS varchar) AS DATETIME)
insert into #RS_GIN_Master(Qty,batch_no,accept_date)
SELECT 10,'BT003', CAST(CAST(2014 AS varchar) + '-' + CAST(8 AS varchar) + '-' + CAST(5 AS varchar) AS DATETIME)
insert into #RS_GIN_Master(Qty,batch_no,accept_date)
SELECT 10,'BT001', CAST(CAST(2014 AS varchar) + '-' + CAST(8 AS varchar) + '-' + CAST(6 AS varchar) AS DATETIME)
/*---------------------------*/
DECLARE #Qty int
DECLARE #batch_no NVARCHAR(max)
DECLARE #accept_date DATETIME
DECLARE myCursor CURSOR FOR
SELECT Qty, batch_no, accept_date FROM #RS_GIN_Master ORDER BY accept_date ASC
OPEN myCursor
FETCH NEXT FROM myCursor INTO #Qty, #batch_no,#accept_date
WHILE (##FETCH_STATUS = 0 AND #requestedAmount > 0 )
BEGIN
Declare #actualQty int
IF #requestedAmount > #Qty
SET #actualQty = #Qty
ELSE
SET #actualQty = #requestedAmount
INSERT INTO #tBatchResults (batch, Amount)
SELECT #batch_no, #actualQty
set #requestedAmount = #requestedAmount - #actualQty
FETCH NEXT FROM myCursor INTO #Qty, #batch_no,#accept_date
END /*WHILE*/
CLOSE myCursor
DEALLOCATE myCursor
RETURN
END
Just make sure to replace the marked part of the function with your query...
You need to create a stored procedure in your database and taking the quantity from your stock table. And you should also have the id of each record to update that records from where u have taken that qty.
Alter PROCEDURE sp_UpdateStockForSale
#batchNO varchar(10),
#qty decimal(9,3)
AS
BEGIN
Create Table #tmpOutput(ID int identity(1,1), StockID int, batchNo varchar(10), qty decimal(9,3));
SET NOCOUNT ON;
DECLARE #ID int;
DECLARE #Stock Decimal(9,3);
DECLARE #TEMPID int;
Select #TEMPID=(Max(ID)+1) From RS_GIN_Master Where qty > 0 And batch_no = #batchNO;
While (#qty > 0) BEGIN
Select #ID=ID, #Stock=qty From RS_GIN_Master Where qty > 0 And batch_no = #batchNO AND ID < #TEMPID Order By accept_date Desc;
--If Outward Qty is more than Stock
IF (#Stock < #qty) BEGIN
SET #qty = #qty - #Stock;
SET #Stock = 0;
END
--If Outward Qty is less than Stock
ELSE BEGIN
SET #Stock = #Stock - #qty;
SET #qty = 0;
END
Insert Into #tmpOutput(StockID,batchNo,qty)Values(#ID,#batchNO,#Stock);
SET #TEMPID = #ID;
--This will update that record don't need it now.
--Update RS_GIN_Master Set qty = #Stock Where ID=#ID
END
Select StockID, batchNo, qty From #tmpOutput;
END
GO
The above example is not compiled but, you can get the logic how you can retrieve the records from your stock table according to FIFO method. You can use accept_date instead of ID in RS_GIN_Master table. but, i would prefer to make it unique so, if i want to get a specific record then it can be possible.
One query .. like this
This should be tweaked for you case as you have groups and other stuff, is only for example purposes.
;with qty as (
select 15 as value
)
,l as (
select
ROW_NUMBER () over (order by accept_date desc) rn
,*
from xxx
)
,q as (
select
batch_no
,accept_date
,case when value>qty then value-qty else 0 end as remainder
,case when value>qty then qty else value end as used
,rn
from l
cross join qty
where rn=1
union all
select
r.batch_no
,r.accept_date
,case when q.remainder>r.qty then q.remainder-r.qty else 0 end as remainder
,case when q.remainder>r.qty then r.qty else q.remainder end as used
,r.rn
from q
join l r
on q.rn+1 = r.rn
where q.remainder!=0
)
select *
from q
where used != 0
and the fiffle for it http://sqlfiddle.com/#!6/9b063/34/0
Below should work for you
Create table RS_GIN_Master
(id int,
qty int,
batch_no varchar(5),
accept_date Datetime
)
GO
Insert into RS_GIN_Master (id, qty, batch_no, accept_date)
values(1,10,'BT001','2018-04-06')
Insert into RS_GIN_Master (id, qty, batch_no, accept_date)
values(2,10,'BT002','2018-04-04')
Insert into RS_GIN_Master (id, qty, batch_no, accept_date)
values(3,15,'BT003','2018-05-06')
GO
----------------------------
CREATE PROC FIFO
#TakenQty int
AS
BEGIN
WITH cte AS (SELECT *, SUM(qty) OVER (ORDER BY accept_date, id ASC) as CumQty FROM RS_GIN_Master WHERE qty>0)
SELECT TOP ((SELECT COUNT(*) FROM cte WHERE CumQty <#TakenQty)+1) batch_no, accept_date,
CASE
WHEN CumQty<#TakenQty THEN qty
ELSE #TakenQty -(CumQty-Qty)
END AS TakenOut
FROM cte
END
Result
| batch_no | accept_date | TakenOut |
|----------|----------------------|----------|
| BT002 | 2018-04-04T00:00:00Z | 10 |
| BT001 | 2018-04-06T00:00:00Z | 5 |
http://www.sqlfiddle.com/#!18/f7ee7/1