How to Compare a empName and Value? - sql

Good morning,
Here is the situation: Have a column of credit card transactions that lists employee names and charge amounts a.k.a debits. In the same column it also lists employee names with an equal negative amount which shows a credit to the account.
What I am trying to do is to find the employee name and charge amount. Then cycle through the list and find the corresponding negative amount.
For example:
John Doe, $100
Jane Doe, $200
Sam Smith, $300
John Doe, -$100
When you run this module your results should return the names of Jane Doe and Sam Smith because only the records for John Doe had both a positive and negative value.
I have gotten very close to an answer but the solution falls apart when there are duplicate values.
For example:
John Doe, $100
John Doe, $100
John Doe, -$100
In this solution the result should be John Doe, $100
So far I have tried with Access, VBA, and SQL but have not come up with an answer.
For the solution, I don't really care if it means adding another object such as a table or a query to perform the comparison part. In the end I need to see a list of matched and unmatched employee names and values.
Additionally, I thought about adding on a column to my table that has a Boolean logic to show the two "matched" records as this will be a database and we don't necessarily want to delete the matched rows from the table master.
Thanks in advance!

You could add a Boolean field Cleared, and then run a simple loop in VBA to mark those set of record that match as cleared:
Public Function ClearTransactions()
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim Criteria As String
Set db = CurrentDb
Set rs1 = db.OpenRecordset("Select * From Transaction Where Value > 0 And Cleared = False Order By Id")
Set rs2 = db.OpenRecordset("Select * From Transaction Where Value < 0 And Cleared = False Order By Id")
While Not rs1.EOF
Criteria = _
"Id > " & rs1!Id.Value & " And " & _
"EmpName = '" & rs1!EmpName.Value & "' And " & _
"Value = " & Str(-rs1!Value.Value) & " And " & _
"Cleared = False"
rs2.FindFirst Criteria
If rs2.NoMatch = False Then
rs1.Edit
rs1!Cleared.Value = True
rs1.Update
rs2.Edit
rs2!Cleared.Value = True
rs2.Update
End If
rs1.MoveNext
Wend
rs2.Close
rs1.Close
Set rs2 = Nothing
Set rs1 = Nothing
Set db = Nothing
End Function

I assume your table has a Primary Key (I'll call it TransactionID and assume it's Long Integer - adjust following code as necessary), in which case I would create a tblMatches with columns DebitID and CreditID to record pairs of entries that tie up. To populate this table:
Dim rsDebits As Recordset
Dim lngCreditID as Long
Set rsDebits = CurrentDb.OpenRecordset ("SELECT * FROM tblTransactions " & _
"WHERE ChargeAmount > 0 And TransactionID Not In " & _
"(SELECT DebitID From tblMatches)")
Do While Not rsDebits.EOF
lngCreditID = Nz(DMin("TransactionID", "tblTransactions", _
"EmpName = '" & rsDebits!EmpName & "' And " _
"ChargeAmount = " & -rsDebits!ChargeAmount & " And " _
"TransactionID Not In (SELECT CreditID From tblMatches)"), 0)
If lngCreditID > 0 Then
CurrentDb.Execute "INSERT INTO tblMatches (DebitID, CreditID) " & _
"VALUES (" & rsDebits!TransactionID & ", " & lngCreditID & ")"
End If
rsDebits.MoveNext
Loop
Set rsDebit = Nothing
You can now write a query joining this tblMatches to tblTransactions (twice, once joined ON tblTransactions.TransactionID = tblMatches.DebitID and the other one ON tblTransactions.TransactionID = tblMatches.CreditID) to show all the various entries that match up. To get a list of unmatched entries you'll need to design a query along the lines of
SELECT * FROM tblTransactions
WHERE TransactionID Not In (Select DebitID From tblMatches)
And TransactionID Not In (Select CreditID From tblMatches)

Related

How to auto-increment primary key in SQL INSERT INTO statement

Private Sub btnAddInfo_Click()
On Error GoTo Error_Routine
'Declare variables
Dim intStudentID As Integer
Dim intTestID As Integer
Dim dblMark As Double
Dim intResultID As Integer
'Declare database
Dim db As DAO.Database
Dim rst As DAO.Recordset
'Set the database
Set db = CurrentDb
Set rst = db.OpenRecordset("Select ResultId FROM StudentResult ORDER BY RESULTID DESC", dbOpenDynaset)
'assign value to intResultID variable
intResultID = rst!ResultId
'Adds the additional 1 to the latest result id that was used
If Not rst.EOF Then
intResultID = intResultID + 1
End If
'Assigns value to variables
intStudentID = Forms!frmAdd!lstStudentID
strDescription = Forms!frmAdd!lstTest
dblMark = txtMark.Value
intTestID = Forms!frmAdd!lstTest
'Checks that Student ID has been selected
If Not IsNull(lstStudentID) Then
'Inserts new test record into StudentResult table
db.Execute "INSERT INTO StudentResult " _
& "(ResultId,StudentId,TestId, Mark) VALUES " _
& "('" & intResultID & "','" & intStudentID & "','" & intTestID & "','" & dblMark & "');"
End If
'Clears fields
txtMark.Value = ""
lstStudentID.Value = ""
lblExistingStudent.Caption = "Existing Student Name:"
'Closes database
Set db = Nothing
I'm trying to add new records. There is a list of 4 tests. ResultId is the primary key and it is an AutoNumber column.
The button adds tests scores just fine if the selected StudentID has not added a score for that TestId yet. But when I try to add a StudentId and TestId combination that has been entered before, it does not add a new record or even update the existing one.
Both StudentId and TestId allow duplicates. I've tried doing this counter variable but it has not worked. This is for a class and the professor says a student should be able to retake tests and it should just add a new record.
Thank you in advance for your help. Please let me know if you need any pictures of the form, tables, or more of my code.
Exclude the AutoNumber field, and don't wrap numbers in quotes:
If Not IsNull(lstStudentID) Then
' Verify values:
Debug.Print "StudentID:", intStudentID, "TestID:", intTestID, "Mark:", Str(dblMark)
'Inserts new test record into StudentResult table
db.Execute "INSERT INTO StudentResult " _
& "(StudentId, TestId, Mark) VALUES " _
& "(" & intStudentID & "," & intTestID & "," & Str(dblMark) & ");"
End If

How to break table rows into new columns?

I made the mistake of structuring some Access tables ineffectively as I was developing a database to store data for my company.
The data pushes and pulls from various models, so I need to restructure the old "labor" tables (each proposal has a labor table) so that any data can be retrieved in the future.
I'm brand new to SQL. I've tried doing this a few different ways (APPEND, ALTER...ADD COLUMN, and others). I think that SELECT...INTO is the way to go at this point, but I still can't get it quite right.
In the old table structure, the first field is "Period." All of the records reappear once for every period. The LCAT, Company, and Salary fields are exactly the same for each period. The only values that change from period to period are the 2 right columns.
I need to restructure these by copying the hours and DLRate values for each period after the 1st into new columns (and rename the Hours/DLRates columns. I've included what I have so far.
Thanks in advance!
| Period LCAT Company Salary Hours DLRate |
|-----------------------------------------|
| 1 LCAT1 Comp1 77000 1723 $37.02|
| 1 LCAT2 Comp1 81000 1723 $38.94|
| 1 LCAT3 Comp2 81000 1723 $50.00|
| 2 LCAT1 Comp1 77000 1800 $38.02|
| 2 LCAT2 Comp1 81000 1800 $39.94|
| 2 LCAT3 Comp2 81000 1800 $51.00|
Option Compare Database
Option Explicit
Sub RedoTables()
Dim sTbl As String
Dim sSQL As String
Dim sTemp As String
Dim intA As Long, intB As Long
Dim arrCols() As String: arrCols() = Split("Hours,DLRate", ",")
sTbl = "Labor"
For intB = 1 To 2
`enter code here`For intA = LBound(arrCols) To UBound(arrCols)
sTemp = "(SELECT " & arrCols(intA) & " FROM [" & sTbl & "] " _
& "WHERE Period = " & intB & ") " _
& "AS P" & intB & "_" & arrCols(intA)
Debug.Print sTemp
sSQL = sSQL & sTemp
If intA < UBound(arrCols) Or intB < 1 Then sSQL = sSQL & ", "
Next
Next
sSQL = "SELECT" & sSQL & " " _
& "INTO [" & sTbl & "test] " _
& "FROM [" & sTbl & "]; "
DoCmd.RunSQL sSQL
End Sub
When I execute the SQL, I am getting an error that states "at most one record can be returned by this subquery"....

iteration (for-loop) ms Access with past value

I tried to translate a code from VBA excel to access. My data is a column of prices and I want to compute the returns.
This is the original VBA code in excel:
DerCol = Cells(T.Row, Columns.Count).End(xlToLeft).Column
Cells(T.Row, DerCol + 1) = "Returns"
For i = T.Row + 2 To T.End(xlDown).Row
Cells(i, DerCol + 1) = Application.WorksheetFunction.Ln(Cells(i, T.Column)) - Application.WorksheetFunction.Ln(Cells(i - 1, T.Column))
Next i
To get an idea of the output that I have in excel, click here.
In Access, I created a new column next to the prices' column and I would like to fill in exactly like in excel:
Sub vardaily()
Dim db As Database, T As Object, DerCol As Integer, y As TableDef
Dim rs As DAO.Recordset, i As Integer, strsql As String
'idea = SELECT prices FROM dailypricing, then creates newtable "VAR", copy and prices, compute historical and parametric VAR '
'create a new table var_daily'
Set db = CurrentDb()
'insert the pricing date and the prices from dbo_daily'
db.Execute "CREATE TABLE VAR_daily" _
& "(PricingDate CHAR, Price Number);"
'where clause to select the same traded product only'
db.Execute " INSERT INTO VAR_daily " _
& "SELECT PricingDate, Price " _
& "FROM dbo_PricingDaily " _
& "WHERE IndexId = 1;"
db.Execute " ALTER TABLE VAR_daily " _
& "ADD COLUMN Returns Number;"
'sql request to store prices'
strsql = "SELECT First(Price) as FirstPrice, Last(Price) as EndPrice FROM VAR_daily;"
'dao.recordset of the store prices'
Set rs = db.OpenRecordset(strsql, dbOpenDynaset)
'loop to change the prices'
For i = 2 To i = rs.RecordCount
rs.Edit
rs!Price(i) = Log(rs!Price(i)) - Log(rs!Price(i - 1))
rs.Update
Next i
db.Execute "INSERT INTO VAR_daily " _
& "(Returns) VALUES " _
& "(" & rs![Price] & ");"
End Sub
I have the following table that you can see here
I can not manage with the loop. I have no item in my collection at the end.
I looked at other example of loops like here but I did not find how to make an iteration with the last result.
Sorry, I really am a beginner in Ms Access and SQL. I started this week so I apologize if my question is very basic.
EDIT: I added the images and I replaced Firsttransaction and Lasttransaction by "FirstPrice" and "EndPrice".
EDIT2: Thanks to my new privilege, I can share a sample for those who are interested.
I have updated your complete code to what it should be. Again, I don't have an Access database handy to test it but it compiles and should work:
Sub vardaily()
Dim db As Database
Dim rs As DAO.Recordset, i As Integer, strsql As String
Dim thisPrice, lastPrice
'idea = SELECT prices FROM dailypricing, then creates newtable "VAR", copy and prices, compute historical and parametric VAR '
'create a new table var_daily'
Set db = CurrentDb()
'insert the pricing date and the prices from dbo_daily'
db.Execute "CREATE TABLE VAR_daily" _
& "(PricingDate CHAR, Price Number);"
'where clause to select the same traded product only'
db.Execute " INSERT INTO VAR_daily " _
& "SELECT PricingDate, Price " _
& "FROM dbo_PricingDaily " _
& "WHERE IndexId = 1 " _
& "ORDER BY PricingDate;"
db.Execute " ALTER TABLE VAR_daily " _
& "ADD COLUMN Returns Number;"
'sql request to retrieve store prices'
strsql = "SELECT * FROM VAR_daily ORDER BY PricingDate;" ' just get all fields
'dao.recordset of the store prices'
Set rs = db.OpenRecordset(strsql, dbOpenDynaset)
'loop to change the prices'
lastPrice = rs.Fields("Price") ' get price from first record and remember
rs.MoveNext ' advance to second record and start loop
While (Not rs.EOF())
thisPrice = rs.Fields("Price")
rs.Edit
rs!Returns = Log(thisPrice) - Log(lastPrice)
rs.Update
lastPrice = thisPrice ' remember previous value
rs.MoveNext ' advance to next record
Wend
End Sub

Get Next Number MS Access

I am trying to create a Work Order System for a company and I am limited to using MS Access. I am wanting to code in a Work Order ID column. This column will be based on 2 combobox options:
BuildingName
TargetDepartment
I need some VBA code to query the WOID column in the table to retrieve the next number. The conditions will be as the below example:
WOID BuildingName TargetDepartment
BUILDA-DEPTA-1 BUILDA DEPTA
BUILDA-DEPTB-1 BUILDA DEPTB
BUILDA-DEPTA-2 BUILDA DEPTA
The VBA code would query the WOID column, and find out if there is a work order for the same building and department and then increment the number at the end by 1. But if there is no WOID that matches the buildingname and targetdepartment, it would create the first entry for that.
So if it finds a matching buildingname and targetdepartment: MaxNumber +1
If it doesn't find a matching buildingname and targetdepartment: 1
Thanks for the help!
You can do this using DLookUp :
where_condition = "[WOID] Like '" & Me.[BuildingNameCombo] & "-" & Me.[TargetDepartmentCombo] & "-*'"
existing_woid = Nz(DLookUp("[WOID]","[TableName]", where_condition),"")
If(existing_woid = "") Then
next_id = 1
Else
next_id = DMax("Mid([WOID], InStrRev([WOID],""-"")+1)","[TableName]", where_condition) + 1
End If
woid = Me.[BuildingNameCombo] & "-" & Me.[TargetDepartmentCombo] & "-" & next_id
You can do it in one line as well, but I think it is better to see the way of thinking behind this.
Edit (with record locking)
Dim s as String, rs as Recordset
s = " Select [WOID] From [TableName] " & _
" Where [WOID] Like '" & Me.[BuildingNameCombo] & "-" & Me.[TargetDepartmentCombo] & "-*'" & _
" Order By 1 Desc"
'This will restrict table access
Set rs = CurrentDb.OpenRecordset(s, dbOpenDynaset, dbDenyRead + dbDenyWrite)
If rs.RecordCount > 0 Then
next_ind = Mid(rs(0), InStrRev(rs(0), "-") + 1) + 1
Else
next_ind = 1
End If
rs.AddNew
rs.Fields("WOID") = Me.[BuildingNameCombo] & "-" & Me.[TargetDepartmentCombo] & "-" & next_ind
rs.Update
rs.Close
Set rs = Nothing

Inserting every OTHER ROW from one table to another (VBA MS Access 2010)

I am working with manually created empty copy of table Products, which I named Products_Backup. What I want to do is to insert every other row from "Spices" category of products into this empty Products_Backup table, since there would be only 6 rows from total of 12 rows, that are in Products table under "Spices" category. The problem is that I don't know how to do that. I tried to use MOD operator for newly created ProductID, but my mentor told me that it is not a proper solution, since he could easily change this ProductID's value and I would get odd rows instead of even.
Private Sub CommandButton0_Click()
Dim db As Database, rst As Recordset
Dim I As Integer, s, s1 As String
Set db = CurrentDb
s = "SELECT Products.* FROM Products WHERE (((Products.CategoryNumber)=2));" ' This value is for Spices
Set rst = db.OpenRecordset(s)
I = 1
While Not rst.EOF
s1 = "INSERT INTO Products_Backup (ProductName, ProductID, CategoryNumber, OrderedUnits) VALUES ('" & rst!ProductName & "', " & I & " , '" & rst!CategoryNumber & "', '" & rst!OrderedUnits & "');"
MsgBox ("Record inserted")
db.Execute s1
I = I + 1
rst.MoveNext
If I Mod 10 = 0 Then
MsgBox ("Inserted " & I & ".record")
End If
Wend
rst.Close
db.Close
End Sub
So with this I can insert all 12 records into Products_Backup, with MsgBox telling me when 10th record was inserted.
But I still have no idea what to do to insert every other row into Products_Backup to get 6 records.
Dim booEveryOther as Boolean
booEveryOther = False
While Not rst.EOF
If booEveryOther Then
s1 = "INSERT INTO ...
End If
booEveryOther = Not booEveryOther
Just use a Boolean value that is set to Not itself with every new record.
i think this should do it better
While Not rst.EOF
s1 = " INSERT INTO Products_Backup (ProductName, ProductID, CategoryNumber, OrderedUnits) " & _
" VALUES ('" & rst!ProductName & "', " & I & " , '" & rst!CategoryNumber & "', '" & rst!OrderedUnits & "');"
db.Execute s1
If I Mod 10 = 0 Then
MsgBox ("Inserted " & I & ".record")
Else
MsgBox ("Record inserted")
End If
I = I + 1
rst.MoveNext
Wend