1

Table Name: Records

ID Date Time Status BoxType Material Rack EmployeeNr Transaction
1 25-05-2020 13:11:12 70 36757 4 4 188 2
2 25-05-2020 13:12:40 71 31178 2 5 188 2
3 25-05-2020 13:13:31 71 31178 2 5 188 102
4 27-05-2020 13:14:14 71 38444 3 2 181 3
5 27-05-2020 13:14:15 71 38444 3 2 181 3
6 27-05-2020 13:14:41 71 38444 3 2 181 3
7 27-05-2020 13:15:10 71 39123 6 5 188 3
8 27-05-2020 13:15:51 71 38444 3 2 181 103
9 27-05-2020 13:16:51 71 38444 3 2 181 103

The Desired OUTPUT I want is Rows 1, 6 and 7

ID Date Time Status BoxType Material Rack EmployeeNr Transaction
1 25-05-2020 13:11:12 70 36757 4 4 188 2
6 27-05-2020 13:14:41 71 38444 3 2 181 3
7 27-05-2020 13:15:10 71 39123 6 5 188 3

Hello dear developer friends,

I have this table "Records". There are two types of transaction viz. 'Forward' and 'Reverse'. The Forward transactions are represented by single to two digits of numbers (that is from 1 to 30) and Reverse transactions are represented by three digits (that is from 100 to 130). Now, every unique Forward transaction has a unique reverse transaction. (For eg. Transaction 1 will have 101, transaction 2 will have 102 and transaction 3 will have 103 and so on).

I do not want to see the Reverse transactions and as well as their forward transactions in my report. (For eg. 102 and 2, 103 and 3) But, I have to find the matching forward transactions whose other columns data (Date, Status,BoxType, Material, Rack,EmployeeNr) are same of Reverse transaction. (As seen in the image, record no. 2 and 3) Also, there can be more than one matches of forward transactions for reverse transactions, and I want to skip only those many forward transactions equal to number of Reverse transactions. (*As seen in the table, record no. 4,5 and 6 matches to record no. 8 and 9, so I want to hide two records no. 4 and 5 with 8 and 9)

So, I tried to write a SQL query, but it is not working in MS access. Appreciate your great help! Thank you! Best Regards.

My code

with table_a as (
  select a.*, row_number() over (partitition by Status, BoxType, Material, Rack, EmployeeNr , Transaction) as dup_n --all columns except ID and time.
  ---for multiple entries of same type
  from Records a
  where Transaction<100
  )
   ,table_b as (
  select b.*, (Transaction-100) as type_new,
         row_number() over (partitition by Status, BoxType, Material, Rack, EmployeeNr , Transaction) as dup_n --all columns except time and ID
         ---for multiple entries of same type
  from Records b
  where Transaction>99
  )
select*from(
  select a.* from table_a
  left join table_b
  on <Status, BoxType, Material, Rack, EmployeeNr , Transaction> --all columns except time and ID
  and a.type = b.type_new
  and a.dup_n = b.dup_n
  )
  where a.Transaction is null
4
  • 1
    So from the sample set shown, exactly which records should be retrieved? Edit question to show sample data as text table, not image, same for desired output. Commented Feb 3, 2021 at 23:12
  • @June7 Hi June7, I have created a text tables. I hope you understands now clearly. Thanks a lot! Commented Feb 4, 2021 at 7:20
  • Returning 1 and 7 is fairly simple, after that I get lost. I considered TOP N per group but N cannot be dynamic in query object. I would probably build a VBA procedure and write records to a temp table. Commented Feb 4, 2021 at 9:44
  • @June7 and how do I acheive this using Access VBA? Commented Feb 4, 2021 at 11:53

1 Answer 1

1

Stackoverflow is not intended to be a code writing service but since you did make attempt with SQL and I was the one who brought up VBA and I was intrigued by the challenge, here is something to give you a start. First, build a 'temp' table - table is permanent but records are temporary - that has same fields as Records table except ID field is not an autonumber, just a number type. Call it RecordsSelected and make sure fields in both tables are in same order in design. Then, build three query objects.

CntRevs:

SELECT [Date], Status, BoxType, Material, Rack, EmployeeNr, Transaction, 
Count(ID) AS CntRev, Val(Mid([Transaction],2)) AS Forward
FROM Records
WHERE (((Records.Transaction)>100))
GROUP BY [Date], Status, BoxType, Material, Rack, EmployeeNr, Transaction, Val(Mid([Transaction],2));

Query1:

SELECT Records.*
FROM Records 
LEFT JOIN (SELECT Records.* FROM Records 
           WHERE (((Records.Transaction)>100))) AS Reverses 
ON (Records.Date = Reverses.Date) 
AND (Records.Status = Reverses.Status) 
AND (Records.BoxType = Reverses.BoxType) 
AND (Records.Material = Reverses.Material) 
AND (Records.Rack = Reverses.Rack) 
AND (Records.EmployeeNr = Reverses.EmployeeNr)
WHERE (((Reverses.Transaction) Is Null));

Query2:

SELECT Records.*, Forward
FROM CntRevs 
INNER JOIN Records ON (CntRevs.EmployeeNr = Records.EmployeeNr) 
AND (CntRevs.Rack = Records.Rack) 
AND (CntRevs.Material = Records.Material) 
AND (CntRevs.BoxType = Records.BoxType) 
AND (CntRevs.Status = Records.Status) 
AND (CntRevs.Date = Records.Date)
AND (CntRevs.Forward = Records.Transaction);

Code in a general module. The result is 3 records identified in your desired output are written to temp table.

Sub Test()
Dim rs1 As DAO.Recordset, rs2 As DAO.Recordset, rs3 As DAO.Recordset, db As DAO.Database
Dim x As Integer
Set db = CurrentDb
db.Execute "DELETE FROM RecordsSelected"
db.Execute "INSERT INTO RecordsSelected SELECT * FROM Query1"
Set rs1 = db.OpenRecordset("SELECT * FROM CntRevs")
Set rs3 = db.OpenRecordset("SELECT * FROM RecordsSelected")
Do While Not rs1.EOF
    Set rs2 = db.OpenRecordset("SELECT * FROM Query2 WHERE Transaction = " & rs1!Forward & " ORDER BY ID DESC")
    If Not rs2.EOF Then
        rs2.MoveLast
        rs2.MoveFirst
        If rs2.recordCount > rs1!CntRev Then
            For x = 1 To rs2.recordCount - rs1!CntRev
                With rs3
                .AddNew
                !ID = rs2!ID
                !Date = rs2!Date
                !Time = rs2!Time
                !Status = rs2!Status
                !BoxType = rs2!BoxType
                !Material = rs2!Material
                !Rack = rs2!Rack
                !EmployeeNr = rs2!EmployeeNr
                !Transaction = rs2!Transaction
                .Update
                End With
                rs2.MoveNext
            Next
        End If
    End If
    rs1.MoveNext
Loop
End Sub
Sign up to request clarification or add additional context in comments.

17 Comments

Thanks a lot June7 for giving me the start in VBA! I tried to run the CntRevs, but it gives me an error that "Cannot group on fields selected with '*' (Records)". I tried to putting column names instead of * after SELECT then it gives me another error "Your Query does not include the specified expression “ID” as part of an aggregate function.". After group by, should I add all columns? Best Regards!
I really appreciate your help! It works for me! You made my weekend! Thanks and words are not enough!!!!!!!!!! Have a nice weekend! Warm Regards.
A side note, Date is a reserved word and really should not use reserved words as object names.
Ooops, forgot rs2.MoveNext line. Also should reference rs1!CntRev instead of rs2. Maybe I did some bad edits again after you implemented. See revised code.
Also a change in Query2 structure.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.