This is probably a very specific issue but I’m quite proud of the solution. And it may prove to be useful to someone else (or me at some other point) so I’m putting it here for posterity.
The issue
We receive a list of sales transactions through an EDI interface. With the implementation of a new retail management system, these transactions now need to be pointed in the direction of the new application. This has proved interesting, on occasion, as the existing system is a lot more forgiving of incomplete data than the new one.
One of these cases, we have discovered, is that for some stores we’re not receiving transaction numbers. We have dates, times, store codes, transaction line numbers – but no transaction numbers. This means that if a store manages to enter two transactions at two tills at exactly the same time, we get a whole bunch of duplicate lines in the interface extract.
This interface is a transitional one (once the roll-out is completed for all stores, it will be redundant) so I shouldn’t be spending too much time on it. Just enough to make it work.
The Solution
Putting together an SQL statement that identifies transactions with duplicate line numbers is pretty easy, as is constructing a statement to update records based on a fixed criteria. The question is, how easy is it to construct an SQL statement to quickly update records based on a dynamic criteria.
The answer is: easier than I expected.
The Implementation
The (slightly simplified) code, is pasted below without explanation but if any part of it is unclear do feel free to either leave a comment or contact me and I will be happy to clarify.
H *------------------------------------------------------------------------* * Program : * * Description : Clean up duplicate lines * * Written by : Paul Pritchard * * Date : 2/07/2012 * *------------------------------------------------------------------------* D pDuplicate DS QUALIFIED D Date 10A D Time 8A D Store 5S 0 D Register 3S 0 D Transaction 5S 0 D Line 3S 0 D* D SaveDate S 10A D SaveTime S 8A D SaveStore S 5S 0 D SaveReg S 3S 0 D SaveTxn S 5S 0 D SaveLine S 3S 0 D* D NewLine S 3S 0 *------------------------------------------------------------------------* /free // The Commitment control workaround exec sql Set Option Commit = *NONE; // Renumber any duplicate lines in the Sales File exsr srDuplicate; // And exit *INLR = *ON; /end-free *------------------------------------------------------------------------* * Subroutine: Renumber any duplicate lines in the Sales interface file * *------------------------------------------------------------------------* /free begsr srDuplicate; // Initialise the work values exsr srReset; // Find the lines with duplicate numbers exec sql declare cSales cursor for with Duplication as (select wrslsdate, wrslstime, wrslsistr, wrslsreg#, wrslstxn#, wrslslin#, count(*) from SALES group by wrslsdate, wrslstime, wrslsistr, wrslsreg#, wrslstxn#, wrslslin# having count(*) > 1 order by wrslsdate, wrslstime, wrslsistr, wrslsreg#, wrslstxn#, wrslslin#) select wrslsdate, wrslstime, wrslsistr, wrslsreg#, wrslstxn#, wrslslin# from SALES where wrslsdate || wrslstime || char(wrslsistr) || char(wrslsreg#) in (select wrslsdate || wrslstime || char(wrslsistr) || char(wrslsreg#) from Duplication) order by wrslsdate, wrslstime, wrslsistr, wrslsreg#, wrslstxn#, wrslslin# for update of wrslslin#; exec sql open cSales; // Start retrieving the data dou SQLCOD = 0 and SQLCOD 100; exsr srRenumber; exec sql update SALES set WRSLSLIN# = :NewLine where current of cSales; endif; enddo; // Close the cursor and quit exec sql close cSales; endsr; /end-free *------------------------------------------------------------------------* * Subroutine: Renumber * *------------------------------------------------------------------------* /free begsr srRenumber; if pDuplicate.Date SaveDate or pDuplicate.Time SaveTime or pDuplicate.Store SaveStore or pDuplicate.Register SaveReg or pDuplicate.Transaction SaveTxn; SaveDate = pDuplicate.Date; SaveTime = pDuplicate.Time; SaveStore = pDuplicate.Store; SaveReg = pDuplicate.Register; SaveTxn = pDuplicate.Transaction; NewLine = 0; endif; NewLine += 1; endsr; /end-free *------------------------------------------------------------------------* * Subroutine: Reset * * Initialise the Save* Values * *------------------------------------------------------------------------* /free begsr srReset; SaveDate = *BLANKS; SaveTime = *BLANKS; SaveStore = *ZERO; SaveReg = *ZERO; SaveTxn = *ZERO; endsr; /end-free *------------------------------------------------------------------------*