Update record if matching values in same table - sql

I have a MS Access database with a list of transactions. I am trying to update a "Match" field on both records where they have some of the same values in fields (Document Number, Voucher Number, Subhead) but opposite amounts. It also needs to avoid duplicates.
Document Number Amount ABS Match
N6809561990112 438.48 438.48
N6809561990112 438.48 438.48
N6809561990112 -438.48 438.48
What I the end result after the SQL should look like
Document Number Amount ABS Match
N6809561990112 438.48 438.48 Y
N6809561990112 438.48 438.48
N6809561990112 -438.48 438.48 Y
The table name is "tblUnmatched"
I tried the following but it updated every record in the table to "Y"
strSql = "Update tblUnmatched SET match = 'Y' WHERE EXISTS(select * " & _
"from tblUnmatched t1 " & _
"inner join tblUnmatched t2 on " & _
"t1.[DOCUMENT NUMBER] = t2.[DOCUMENT NUMBER]" & _
"where t1.ABS = t2.ABS AND t1.AMOUNT <> t2.AMOUNT AND t1.SUBH = t2.SUBH)"
DoCmd.RunSQL strSql
I also tried this but it couldn't handle the duplicate problem.
strSql = "Update tblUnmatched SET match = 'Y' WHERE [DOCUMENT NUMBER] IN(select t1.[DOCUMENT NUMBER] " & _
"from tblUnmatched t1 " & _
"inner join tblUnmatched t2 on " & _
"t1.[DOCUMENT NUMBER] = t2.[DOCUMENT NUMBER]" & _
"where t1.ABS = t2.ABS AND t1.AMOUNT <> t2.AMOUNT AND t1.SUBH = t2.SUBH)"
DoCmd.RunSQL strSql

Your task is impractical in Access SQL without a primary key field. Although there is no such key in the data source you import, that does not prohibit you from adding one in Access.
Add an autonumber primary key, id, to tblUnmatched. Then for each new batch of incoming data:
import into a scratch table, tblScratch
DELETE FROM tblUnmatched
append the rows from tblScratch into tblUnmatched
(The process could be cleaner if you can use SELECT FROM <your data source> to append directly to tblUnmatched, instead of first importing to tblScratch.)
Save the following SELECT statement as qryFindMatches:
SELECT
sub.[Document Number],
sub.Amount,
sub.MinOfid,
DCount(
"*",
"tblUnmatched",
"[Document Number]='" & [Document Number]
& "' AND Amount = -1 * " & [Amount]
) AS match_count
FROM
(
SELECT [Document Number], Amount, Min(id) AS MinOfid
FROM tblUnmatched
GROUP BY [Document Number], Amount
) AS sub;
Then the UPDATE you want can be fairly easy to create. Beware the performance may not be blazing fast; hopefully you can accommodate it once a month.
UPDATE tblUnmatched
SET [Match] = True
WHERE id In
(
SELECT MinOfId
FROM qryFindMatches
WHERE match_count > 0
);
I added an additional row to your sample data and tested with Access 2007. I think this is what you want ...
id Document Number Amount Match
1 N6809561990112 $438.48 True
2 N6809561990112 $438.48 False
3 N6809561990112 ($438.48) True
4 N6809561990112 $5.00 False

Related

SQL Join fields from 3 tables

I have 3 tables of data that I need to join to make one table and show the following fields:
u.master_id, p.surname, p.forename1, c.number, u.status
Here are the table details:
Table 1 (person p)
Field name = entity_id (number)
Field name = surname(text)
Field name = forename1(text)
Field name = auditflag
Table 2 (users u)
Field name = master_id (number)
Field name = email (number)
Field name = status (text)
Field name = auditflag
Table 3 (contact c)
Field name = master_id (number)
Field name = entity_id (number)
Field name = number (text = holds the actual email address)
Field name = auditflag
The master_id field from table 2 and 3 links to the person entity_id ( master_id=p.entity_id )
The email field from table 2 links to the entity_id in table 3 ( u.email=c.entity_id ) to get the number
The auditflag is used to mark each as an active record i.e. ( p.auditflag=1 AND u.auditflag=1 AND c.auditflag=1 )
I'm using Excel 2010 VBA - joining to a PostGreSQL database to get the data.
Below is the code I am using to join the 2 tables which works fine, but my problem is that "email" only shows a number because the actual address is in a 3rd table (Contact) under the field called "number".
I don't know how to include the 3rd table to show the field c.number in my query.
Const sqlconnection = "Provider=oledb;"
Dim conn As New Connection
conn.ConnectionString = sqlconnection
conn.Open
Dim rs As Recordset
Dim prs As String
prs = "SELECT u.master_id, p.surname, p.forename1, u.email, u.status " _
& "FROM users u INNER JOIN person p ON u.master_id=p.entity_id " _
& "WHERE u.auditflag=1 AND p.auditflag=1 " _
& "ORDER BY u.master_id "
Set rs = conn.Execute(prs)
With ActiveSheet.QueryTables.Add(Connection:=rs, Destination:=Range("A1"))
.Refresh
End With
You have all the pieces; all you need to do is add the third table to the query and select the columns you want.
Dim prs As String
prs = "SELECT u.master_id, p.surname, p.forename1, c.number as email, u.status " _
& "FROM users u INNER JOIN person p ON u.master_id=p.entity_id " _
& " INNER JOIN contact c ON c.master_id=p.entity_id and u.email=c.entity_id " _
& "WHERE u.auditflag=1 AND p.auditflag=1 AND c.auditflag=1 " _
& "ORDER BY u.master_id "
As written, this query will only get users that have active (auditflag=1) person rows and active contact rows. Changing to left joins and moving the auditflag checks to the join condition would allow returning users without active rows in all three tables.
As a side note, I find the column names in your tables are actively working against easily understanding what they mean; if you can, I'd suggest re-thinking the names you're using.

Query to return the Max(Date) and other table fields based on a primary table list

I am hoping somebody out there can help me with a query problem I can’t seem to resolve;
I have two tables;
Table1
T1_ID
T1_Serial
Table2
T2_ID
T1_ID –lookup to Table 1
T2_Date
T2_History
Table1 Data might look something like this;
T1_ID T1_Serial
1, ABC1
2, ABC2
3, ABC3
4, ABC4
Table2 Data might look like this;
T2_ID, T1_ID, T2_Date, T2_History
1, 1, 05/05/15, “Some History1”
2, 1, 05/17/15, “Some History2”
3, 2, 05/09/15, “Some History3”
4, 2, 05/21/15, “Some History4”
5, 3, 05/12/15, “Some History5”
I would like to set up a query to give me the record containing Max(Date) of table History for each record in table Units
Table1.T1_Serial , Max(T2_Date), T2_History;
For this example;
ABC1 05/17/15 “Some History2”
ABC2 05/21/15 “Some History4”
ABC3 05/12/15 “Some History5”
I have constructed the SQL to give me the T1_Serial and Max(Date), which is working correctly;
SELECT Table2.T1_ID, Max(Table2.T2_Date) AS MaxDate
FROM Table2
GROUP BY Table2.T1_ID;
But when I try adding the T2_History to the query I end up getting all the other history besides the Max(Date).
Hope someone can lead me on the right path. Thanks!
I use similar approach as Sam. But removed the T2_ID from the wrapped SQL to avoid issues with the GROUP BY. Also Join by Date.
SQL Fiddle
WITH MaxDate (T1_ID, MaxDate) as
(
SELECT T1_ID, Max(Table2.T2_Date) AS MaxDate
FROM Table2
GROUP BY Table2.T1_ID
)
SELECT T1_Serial, T2_Date, T2_History
FROM
MaxDate
INNER JOIN Table2 ON MaxDate.MaxDate = Table2.T2_Date
INNER JOIN Table1 ON MaxDate.T1_ID = Table1.T1_ID;
vba version fiddle
SELECT tbl_RMAunit.RMA_SN, tbl_History.Hist_Date,tbl_History.Hist_History
FROM (
SELECT RMA_ID, Max(tbl_History.Hist_Date) as MaxDate
FROM tbl_History
Group by tbl_History.RMA_ID
) MaxDate
Inner Join tbl_History on MaxDate.MaxDate = tbl_History.Hist_Date
Inner Join tbl_RMAunit on MaxDate.RMA_ID = tbl_RMAunit.RMA_ID
I found this example for nested queries on VBA. But i couldnt try it. Good luck.
Sub TestNestedQuery()
Dim RS As DAO.Recordset, strSql As String
Dim qdfTemp As QueryDef
Dim qdfNew As QueryDef
Dim strSQL1 as string
Dim strSQL2 as string
strSQL1 = "SELECT RMA_ID, Max(tbl_History.Hist_Date) as MaxDate " & _
"FROM tbl_History " & _
"Group by tbl_History.RMA_ID"
strSQL2 = "SELECT tbl_RMAunit.RMA_SN, tbl_History.Hist_Date,tbl_History.Hist_History " & _
"FROM qryTemp " & _
"Inner Join tbl_History on qryTemp.MaxDate = tbl_History.Hist_Date " & _
"Inner Join tbl_RMAunit on qryTemp.RMA_ID = tbl_RMAunit.RMA_ID "
With CurrentDb()
Set qdfTemp = .CreateQueryDef("qryTemp", strSQL1) '' SQL 1
Set qdfNew = .CreateQueryDef("qryNew", strSQL2)' SQL 2
GetrstTemp qdfNew
''' Delete the two querydefs if necessary
.QueryDefs.Delete qdfTemp.Name
.QueryDefs.Delete qdfNew.Name
End With
End Sub
Function GetrstTemp(qdfTemp As QueryDef)
Dim rstTemp As DAO.Recordset
Dim i As Integer: i = 0
With qdfTemp
Debug.Print .Name
Debug.Print " " & .sql
'' Open Recordset from QueryDef.
Set rstTemp = .OpenRecordset(dbOpenSnapshot)
Do While Not rstTemp.EOF
i = i + 1
Debug.Print rstTemp.Fields("RMA_SN") '' Change the field name
Debug.Print rstTemp.Fields("Hist_Date") '' Change the field name
rstTemp.MoveNext
Loop
Debug.Print
Debug.Print " Number of records = " & _
rstTemp.RecordCount
End With
End Function

Access Select Query to show the same field with a different criteria

I have a select query in Access 2010 which shows a 'Level Name' where the 'Period ID' is set to 1
How can i add another field to the query which also shows the Level Name where the Period ID is set to 2?
I would like them both to be next to each other in separate rows
For reference, my current query looks like:
SELECT
qryMaster.[First Name] & " " & qryMaster.[Last Name] AS ChildName,
qryMaster.LevelName
FROM
qryMaster
WHERE
(
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 1)
);
I have added a picture of how my current query looks like in a sub form. I would like a new Column next to september, but for a different period
A WHERE clause is always for all fields. So if you want two different WHERE clauses then you need two queries.
Otherwise try
AND (qryMaster.PeriodID In(1,2))
I know this thread was active five month ago, but I had the same problem, found this page with google. Asuming others will arrive here too, I'll post the two solutions that I found below.
SELECT t1.ChildName, t1.LevelName1, qryMaster.LevelName
FROM
((SELECT
qryMaster.[First Name] & " " & qryMaster.[Last Name] AS ChildName,
qryMaster.LevelName as LevelName1
FROM qryMaster
WHERE
(
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 1)
)) AS t1)
LEFT JOIN qryMaster
ON t1.ChildName = (qryMaster.[First Name] & " " & qryMaster.[Last Name])
WHERE (
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 2)
)
As I do not have your data I couldn't test the code for your data, therefore I am not sure whether the "ON" clause works like this. In my case I have some customer ID there.
And the second one:
SELECT t1.[First Name] & " " & t1.[Last Name] AS ChildName, t1.LevelName AS LevelName1, t2.levelName AS LevelName2
FROM qryMaster t1
INNER JOIN qryMaster t2 ON t1.Childname=(t2.[First Name] & " " & t2.[Last Name])
WHERE (
(t1.ClassID = [Forms]![frmViewRecords_subject]![cboClass]) AND
(t1.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject]) AND
(t1.PeriodID = 1) AND
(t2.ClassID = [Forms]![frmViewRecords_subject]![cboClass]) AND
(t2.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject]) AND
(t2.PeriodID = 2)
)

Insert Into SQL VBA

I am trying to select records that are in the first table but not in the second table and insert them into the second table using a sql statement in VBA. I have started it below but I am not sure why it won't work. I am rather new to sql so any help would be greatly appreciated.
MySQL = "INSERT INTO Clients ()" & _
"SELECT DISTINCT DD.[Client ID] " & _
"FROM " & tableName & " as DD " & _
"Where DD.[Client ID] NOT IN (SELECT DD.[Client ID] FROM " & tableName & " as DD)"
First, you need supply field list to insert statement:
INSERT INTO Clients (ClientID)...
Second, your query doesn't insert any rows, because you check ClientID presence in same table. Did you mean someting like next:
"Where DD.[Client ID] NOT IN (SELECT DD2.[Client ID] FROM " & tableName2 & " as DD2)"

Multiple select statements in access vba

I am trying to insert 2 count numbers into a table as one record in access through vba and for some reason it is saying the number of query values and destination fields are not the same when I try to run it. I am very confused why this is happening. Any help would be greatly appreciated
TotalVerified = " INSERT INTO Totals([TOTAL VERIFIED FORMULARIES], [TOTAL AVAILABLE FOR IMPORT]) " & _
"SELECT COUNT([FORMULARY ID]) " & _
"FROM VerifiedFormularies " & _
"AND COUNT([FORMULARY ID])" & _
"FROM ImportMetricsIDs"
I think the query you want is:
INSERT INTO Totals([TOTAL VERIFIED FORMULARIES], [TOTAL AVAILABLE FOR IMPORT])
SELECT CNT1, CNT2
FROM (SELECT COUNT([FORMULARY ID]) as CNT1 FROM VerifiedFormularies) as c1 CROSS JOIN
(SELECT COUNT([FORMULARY ID]) as CNT2 FROMImportMetricsIDs) as c2;
AND is a boolean operator, typically used in a WHERE clause, ON clause, or in an iif() expression. It doesn't connect the values from two subqueries.