MS Access SQL - Problem with subquery and function in ORDER BY clause - sql

The senario is that some people apply for some positions.
So there are tApplicant, tPosition and a join table tPreferences for a many-to-many relationship between them.
I need to build a SQL expression where these should happen:
get some fields from a join of tApplicant and tPosition into a new table.
create a new field called AM which should be either 1 or 0.
1 = If tApplicant.applicationID is found in a third not relevant table called tInfo.
0 = If tApplicant.applicationID is not found there.
ORDER BY AM.
It is executed in VBA. This is what I 've got so far:
sSQL = "SELECT tApplicant.applicationID, tApplicant.name, tApplicant.ID, tPreferences.fld3, " & _
"NZ((SELECT 1 FROM tInfo WHERE tInfo.applicationID = tApplicant.applicationID), 0) AS AM " _
"INTO " & sTable & " FROM tPreferences INNER JOIN tApplicant " & _
"ON tPreferences.IDapplic = tApplicant.applicationID " & _
"WHERE tPreferences.IDposit = " & rsRos!ID & ";"
CurrentDB.Execute sSQL, dbFailOnError
It seems like step 3 cannot be done.
Adding ORDER BY AM, throws Run-time error '3061'. Too few parameters. Expected 1..
While adding ORDER BY NZ((SELECT 1 FROM tInfo WHERE tInfo.applicationID = tApplicant.applicationID), 0), throws Run-Time Error 3075: Syntax Error in Query Expression 'NZ((SELECT 1 FROM tAMEA WHERE tAMEA.aitisiID = tAiton.aitisiID), 0'..
If omitted, everything works fine but there's no ORDER BY.
How can I achieve this?
PS: If values 1 and 0 for AM make things complicated, and some other values instead could be easier to get with the query, it will be OK, I will deal with this in the rest of the code.

Nz is an application-level function (technically, a method of the Access.Application object exposed as a function. It is unavailable for use in DAO.
CurrentDb.Execute is using DAO.
There are two rewrite possibilities:
Rewrite to avoid Nz:
IIF((SELECT 1 FROM tInfo WHERE tInfo.applicationID = tApplicant.applicationID) IS NOT NULL, 1, 0)
Or my preferred rewrite:
ORDER BY EXISTS(SELECT 1 FROM tInfo WHERE tInfo.applicationID = tApplicant.applicationID) DESC
Rewrite to DoCmd.RunSQL which does allow these functions (and suppress warnings as desired:
DoCmd.RunSQL sSQL

First, Access might think that the subquery may return more than one record, thus Top 1 should be used.
Next, it makes no sense to order the records to be inserted, as records per definition carries no order unless you specify this in the target table or the query where that table is used as source.
Also, even if you insisted to sort the insert, Access can't do this, as it doesn't know the output for AM.
Thus, this will run:
sSQL = "SELECT tApplicant.applicationID, tApplicant.name, tApplicant.ID, tPreferences.fld3, " & _
"NZ((SELECT Top 1 1 FROM tInfo WHERE tInfo.applicationID = tApplicant.applicationID), 0) AS AM " _
"INTO " & sTable & " FROM tPreferences INNER JOIN tApplicant " & _
"ON tPreferences.IDapplic = tApplicant.applicationID " & _
"WHERE tPreferences.IDposit = " & rsRos!ID & ";"
CurrentDB.Execute sSQL, dbFailOnError
That said, Erik's suggestion to replace Nz with Exists is preferable as this will result in "clean SQL" which always will run faster:
sSQL = "SELECT tApplicant.applicationID, tApplicant.name, tApplicant.ID, tPreferences.fld3, " & _
"EXISTS (SELECT Top 1 1 FROM tInfo WHERE tInfo.applicationID = tApplicant.applicationID) AS AM " _
"INTO " & sTable & " FROM tPreferences INNER JOIN tApplicant " & _
"ON tPreferences.IDapplic = tApplicant.applicationID " & _
"WHERE tPreferences.IDposit = " & rsRos!ID & ";"
CurrentDB.Execute sSQL, dbFailOnError
Neither will this be sortable on AM. Also, it will in Access SQL return -1 and 0 for AM. To obtain 1, apply ABS:
sSQL = "SELECT tApplicant.applicationID, tApplicant.name, tApplicant.ID, tPreferences.fld3, " & _
"ABS(EXISTS (SELECT Top 1 1 FROM tInfo WHERE tInfo.applicationID = tApplicant.applicationID)) AS AM " _
"INTO " & sTable & " FROM tPreferences INNER JOIN tApplicant " & _
"ON tPreferences.IDapplic = tApplicant.applicationID " & _
"WHERE tPreferences.IDposit = " & rsRos!ID & ";"
CurrentDB.Execute sSQL, dbFailOnError

#ErikA and #Gustav 's answers pointed me to the right direction. Thank you both for your time.
The problem in this case was that I tried to use a subquery in the ORDER BY clause. Which I found out now that is not allowed. eg. see here
More over, I found this question, which makes mine a possible duplicate. Here it is suggested to wrap the query.
So I firstly SELECT the data in no order with the subquery and then, INSERT INTO the new table using ORDER BY with the new column of the subquery.
So I'm posting what finally worked for me.
sSQL = "SELECT * INTO " & sTable & " FROM (" & _
"SELECT tApplicant.applicationID, tApplicant.name, tApplicant.ID, tProtimisi.fld3, " & _
"NZ((SELECT 1 FROM tInfo WHERE tInfo.applicationID = tApplicant.applicationID), 0) AS AM " & _
"FROM tPreferences INNER JOIN tApplicant " & _
"ON tPreferences.IDapplic = tApplicant.applicationID " & _
"WHERE tPreferences.IDposit = " & rsRos!ID & ") " & _
"ORDER BY AM DESC;"
CurrentDb.Execute sSQL, dbFailOnError

Related

SQL query assistance needed with 'NOT'

I'm working out of VB6 with SQL SERVER 2012. I found myself in a pickle. Basically i have a query that works fine and pulls the necessary data in SQL SERVER, however, I'm having a difficult time translating it to vb6 SQL code. Here's a working query in SQL SERVER...
SELECT 'TotalSum' = SUM(Units)
FROM tblDetail
WHERE MemberID = '117'
AND CAST(SStartD AS DATETIME) >= '4/1/2016'
AND CAST(SStartD AS DATETIME) <= '4/7/2016'
AND Service = 166
AND [CODE] IN('1919')
AND NOT(InvoiceNo = '11880'
AND DtlNo = 2
)
AND NOT(InvoiceNo = '11880'
AND AdjNo = 2
);
So when I try to write it in my vb6 application i do something like
SELECT 'TotalSum' = SUM(Units)
FROM tblDetail
WHERE MemberID = '117'
AND CAST(SStartD AS DATETIME) >= '4/1/2016'
AND CAST(SStartD AS DATETIME) <= '4/7/2016'
AND Service = 166
AND [CODE] IN('1919')
AND (InvoiceNo <> '11880'
AND DtlNo <> 2
)
AND (InvoiceNo <> '11880'
AND AdjNo <> 2
);
However, this is not giving me the same results. Whats happening is in my last two clauses
( InvoiceNo <> '11880' AND DtlNo<> 2) AND (InvoiceNo <> '11880' AND AdjNo <> 2)
When I run them finally in SQL SERVER don't have paranthesis and its absolutely detrimental that the 2 seperate clauses are in paranthesis. Anyone know what I can do? I think my last resort might be to create a store procedure but i don't really want to do that.
EDIT:
g_SQL = "SELECT 'SUM' = SUM(Units) " & _
"FROM tblDetail WHERE " & _
"MemID = " & udtCDtl.Lines(udtCDtlIdx).MemID & " AND " & _
"CAST(SStartD As DateTime) >= '" & StartDate & "' AND " & _
"CAST(SStartD As DateTime) <= '" & DateAdd("d", -1, EndDate) & "' AND " & _
"Service = 166 AND " & _
"[CODE] IN (‘1919’)) And " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"DtlNo <> " & (InvoiceDtlRS! InvoiceDtlNo, "")) & " AND " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"AdjNo <> " & InvoiceDtlRS! InvoiceDtlNo)
Your translation of NOT(InvoiceNo = '11880' AND DtlNo = 2) to (InvoiceNo <> '11880' AND DtlNo <> 2) is incorrect.
In formal logic, !(A & B) is equivalent to (!A or !B), so it should be:
(InvoiceNo <> '11880' OR DtlNo <> 2)
This is why you're getting different results. However, why not use the original query? There's nothing in VB6 which would prevent it.
EDIT
g_SQL = "SELECT 'SUM' = SUM(Units) " & _
"FROM tblDetail WHERE " & _
"MemID = " & udtCDtl.Lines(udtCDtlIdx).MemID & " AND " & _
"CAST(SStartD As DateTime) >= '" & StartDate & "' AND " & _
"CAST(SStartD As DateTime) <= '" & DateAdd("d", -1, EndDate) & "' AND " & _
"Service = 166 AND " & _
"[CODE] IN (‘1919’)) And " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"DtlNo <> " & (InvoiceDtlRS! InvoiceDtlNo, "")) & " AND " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"AdjNo <> " & InvoiceDtlRS! InvoiceDtlNo)
You've got a ) in the wrong place twice. Also, the ) on the final live would be a syntax error I think. The last 5 lines should be:
"[CODE] IN (‘1919’) And " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"DtlNo <> " & (InvoiceDtlRS!InvoiceDtlNo, "") & " AND " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"AdjNo <> " & InvoiceDtlRS!InvoiceDtlNo & ")"
This should work. I'm able to use SQL queries using NOT with ADODB in VB6.
g_SQL = "SELECT 'SUM' = SUM(Units) " & _
"FROM tblDetail WHERE " & _
"MemID = " & udtCDtl.Lines(udtCDtlIdx).MemID & " AND " & _
"CAST(SStartD As DateTime) >= '" & StartDate & "' AND " & _
"CAST(SStartD As DateTime) <= '" & DateAdd("d", -1, EndDate) & "' AND " & _
"Service = 166 AND " & _
"[CODE] IN ('1919')) And " & _
"NOT (InvoiceNo = " & InvoiceDtlRS!InvoiceHdrNo & " AND DtlNo = " & InvoiceDtlRS!InvoiceDtlNo & ") AND " & _
"NOT (InvoiceNo = " & InvoiceDtlRS!InvoiceHdrNo & " AND AdjNo = " & InvoiceDtlRS!InvoiceDtlNo & ")"
While Marc may have given you a query that works, Simon's question is still valid. The only reason your original query wouldn't work is because you munged the quotes. You'll notice that your parentheses by the reference to InvoiceNo are outside the quotes rather than inside them (there are other problems as well, from changing your original query, but I'll leave you to figure those out for yourself). That makes them not part of the quoted string, and instead part of the VB6 expression. Frankly, Marc isn't doing you any favors by providing an alternative SQL query that happens to have all the VB6 syntax correct, while yours does not. The real problem is that you haven't worked out how to put a SQL query into a quoted string carefully enough.
You can't afford that kind of carelessness if you want to be good at what you're doing. I don't say this to be offensive, but to get your attention. By adopting Marc's solution as the correct one, you haven't really solved your problem, because your problem is a mindset that doesn't think about anything except getting something to work. That mindset makes for the worst kind of programmer, the kind that writes terrible code (hundreds of lines of code where it could be done in 10, for example) that makes nightmares for people who have to maintain it later. Don't be one of those people. When you don't know why something isn't working, go to the trouble of figuring out why. You only have to do it once for each problem, and that mindset will stand you well as you continue to develop your skills.
Again, no disrespect intended. I'm just trying to get you to understand how to avoid getting in "pickles" like this one in future. Hopefully, the next time you post a question here, the "pickle" you're in will be more sophisticated. :)
EDIT: I guess I'm not making myself clear enough. The simple rule is that you need to enclose everything in the working SQL query in quoted strings, and replace the literal search values with references to text boxes, fields, or whatever. So:
sql = "SELECT 'TotalSum' = SUM(Units) " & _
"FROM tblDetail " & _
"WHERE MemberID = '" & myVariable & "' " & _
"AND CAST(SStartD AS DATETIME) >= '" & myVariable & "' " & _
"AND CAST(SStartD AS DATETIME) <= '" & myVariable & "' " & _
"AND Service = 166 " & _
"AND [CODE] IN('1919') " & _
"AND NOT(InvoiceNo = '" & myVariable & "' " & _
"AND DtlNo = " & myVariable & _
")" & _
"AND NOT(InvoiceNo = '" & myVariable & "' " & _
"AND AdjNo = " & myVariable & _
");"
Where myVariable is whatever variable reference you want to replace your literal string with. Any examples you've given have errors in placement of double quotes, which is why you aren't getting the result you want, which is presumably a replication of your working SQL query. The reason Marc's works is not because he altered your original query (it doesn't look like he has, except to put it on less lines) but because he placed his quotation marks correctly. The reason your and simon's solutions don't work is because neither of you have. Going back to your original post, the reason that the parentheses fail to show is because you haven't enclosed them in quotes. Marc has.

How to get last 5 games of a team out of my access database

Hi all below you see a screenshot of my database:
But now I want to be able to make a table that calculates every players last 5 games. As I'm totaly new to access db I really have no clue how to do this.
Can you guys help me a hand with this one?
When I use the 2nd snippet in the answer below I get these:
Below are SQL routes according to your data. To use in MS Access simply create a new query under Create Tab on Ribbon and place the below SQL in the SQL view of a new created query. You may need to adjust query according to your actual table names and/or fields.
SAME GAMES FOR ALL PLAYERS
Assuming every player shares the same last five games, you could run an aggregate query across all players, using a subquery in INNER JOIN clause to calculate last five game dates. Do note: subquery, LastFiveDates can be saved as its own query and used directly in INNER JOIN.
SELECT [LookUp to Players],
Sum(GamesWon) As SumOfGamesWon, Sum(GamesLost) As SumOfGamesLost,
Sum(OwnOdds) As SumOfOwnOdds, Sum(OppOdds) As SumOfOppOdds,
Sum(GamesPlayed) As SumOfGamesPlayed
FROM GamesTable
INNER JOIN
(
SELECT DISTINCT TOP 5 [Date]
FROM GamesTable
ORDER BY [Date] DESC
) As LastFiveDates
ON GamesTable.[Date] = LastFiveDates.[Date]
GROUP BY [LookUp to Players];
DIFFERING GAMES FOR EACH PLAYER
SIMPLE SELECT APPROACH
Now, if players differ in their last five games, you have to join on different queries or union queries. Again, the below uses a subquery in an inner join but you can save that LastFiveGames as its own stored query and join in INNER JOIN line.
SELECT GamesTable.[LookUp to Players],
Sum(GamesWon) As SumOfGamesWon, Sum(GamesLost) As SumOfGamesLost,
Sum(OwnOdds) As SumOfOwnOdds, Sum(OppOdds) As SumOfOppOdds,
Sum(GamesPlayed) As SumOfGamesPlayed
FROM GamesTable
INNER JOIN
(
SELECT [Lookup to Players], [Date],
(SELECT Count(*)
FROM GamesTable t2
WHERE GamesTable.[Date] <= t2.[Date]
AND GamesTable.[Lookup to Players] = t2.[Lookup to Players]) AS GameOrder
FROM GamesTable
) As LastFiveDates
ON GamesTable.[Date] = LastFiveDates.[Date]
AND GamesTable.[Lookup to Players] = LastFiveDates.[Lookup to Players]
WHERE LastFiveDates.GameOrder <= 5
GROUP BY GamesTable.[LookUp to Players];
DIFFERING GAMES FOR EACH PLAYER
VBA CREATE TABLE APPROACH
Due to performance issues of Access running the query as a stored query, VBA can re-create the GamesStats iteratively looping through all distinct players using the very first query condition for player.
Public Function GameTableStats()
Dim db As Database
Dim tbldef As TableDef, rst As Recordset
Dim strSQL As String, i As Integer
Set db = CurrentDb
Set rst = db.OpenRecordset("SELECT DISTINCT PlayerName FROM GamesTable", dbOpenDynaset)
For Each tbldef In db.TableDefs
If tbldef.Name = "GamesStats" Then
db.Execute "DROP TABLE [GamesStats]", dbFailOnError
End If
Next tbldef
rst.MoveLast
rst.MoveFirst
i = 1
Do While Not rst.EOF
If i = 1 Then
' FIRST PLAYER (MAKE-TABLE QUERY) '
strSQL = "SELECT GamesTable.[PlayerName]," _
& " Sum(GamesWon) As SumOfGamesWon, Sum(GamesLost) As SumOfGamesLost," _
& " Sum(OwnOdds) As SumOfOwnOdds, Sum(OppOdds) As SumOfOppOdds," _
& " Sum(GamePlayed) As SumOfGamePlayed" _
& " INTO GamesStats" _
& " FROM GamesTable" _
& " INNER JOIN" _
& " (" _
& " SELECT DISTINCT TOP 5 [Date], [PlayerName]" _
& " FROM GamesTable" _
& " WHERE [PlayerName]=""" & rst!PlayerName & """" _
& " ORDER BY [Date] DESC" _
& " ) As LastFiveDates" _
& " ON GamesTable.[Date] = LastFiveDates.[Date]" _
& " WHERE GamesTable.[PlayerName]= """ & rst!PlayerName & """" _
& " GROUP BY GamesTable.[PlayerName];"
Else
' ALL OTHER PLAYERS (INSERT APPEND QUERIES) '
strSQL = "INSERT INTO GamesStats ([PlayerName], [SumOfGamesWon], [SumOfGamesLost]," _
& " [SumOfOwnOdds], [SumOfOppOdds], [SumOfGamePlayed])" _
& " SELECT GamesTable.[PlayerName], " _
& " Sum(GamesWon) As SumOfGamesWon, Sum(GamesLost) As SumOfGamesLost, " _
& " Sum(OwnOdds) As SumOfOwnOdds, Sum(OppOdds) As SumOfOppOdds, " _
& " Sum(GamePlayed) As SumOfGamePlayed " _
& " FROM GamesTable " _
& " INNER JOIN " _
& " ( " _
& " SELECT DISTINCT TOP 5 [Date], [PlayerName] " _
& " FROM GamesTable " _
& " WHERE [PlayerName]=""" & rst!PlayerName & """" _
& " ORDER BY [Date] DESC" _
& " ) As LastFiveDates " _
& " ON GamesTable.[Date] = LastFiveDates.[Date]" _
& " WHERE GamesTable.[PlayerName]= """ & rst!PlayerName & """" _
& " GROUP BY GamesTable.[PlayerName];"
End If
db.Execute strSQL, dbFailOnError
i = i + 1
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
Set db = Nothing
MsgBox "Successfully created GamesStats table!", vbInformation
End Function

ADO Repeated SQL Parameters

I have a query that uses a sub query with the same parameters, so it looks something like this:
strSelect = _
"SELECT a.State, a.FirstName, a.LastName, b.JobTitle " & _
"FROM apples a " & _
"LEFT JOIN ( " & _
"SELECT a.RecordNumber, " & _
"CASE WHEN j.JobTitle IS NULL THEN j.JobTitle2 ELSE j.jobtitle END " & _
"FROM apples a " & _
"LEFT JOIN jobs j ON j.RecordNumber = a.RecordNumber " & _
strWhere & _
") b ON b.RecordNumber = a.RecordNumber "
strWhere = _
"WHERE a.JobState = ? " & _
"AND a.JobDate = ? "
The sub-query in real life is less pointless than the one in the example.
The question here is if I repeat strWhere, then is there a way to get the parameters to work for the resulting strSQL = strSelect & strWhere statement? The issue is that I have two parameters, but they're repeated, so it would be four parameters for the strSQL statement, but I would prefer to not repeat my parameters when I declare them.
I have a feeling I'm missing something pretty obvious here. Any suggestions?
You should use named parameters:
Try using named parameters for example:
WHERE a.JobState = #JobDate
and
AND a.JobDate = #JobDate
Then, when you add your parameters you will only need to add them once. It will look something like this:
SqlParameter param = new SqlParameter();
param.ParameterName = "JobDate";
param.Value = theDate;

How do I delete files from a table in MSDE 2000 that is selected by 3 joins?

I have a VB6 program that uses a n Access backend. The query that I am currently using is
sQuery = "DELETE tblResultNotes.* " & _
"FROM (tblJobs INNER JOIN tblResults ON tblJobs.JobID=tblResults.JobID) INNER JOIN tblResultNotes ON tblResults.ResultID=tblResultNotes.ResultID " & _
"WHERE (tblJobs.CreateDate)< #" & strDate & "# " & _
"AND tblResults.StartTime < #" & strDate & "#;"
I have changed my backend to MSDE 2000 and now this query is giving me a syntax error near '*'. Could someone help me out?
Thanks,
Tom
Try changing your SQL to this:
sQuery = "DELETE FROM tblREsultNotes " & _
"FROM " & _
" tblJobs" & _
" INNER JOIN tblResults ON tblJobs.JobID=tblResults.JobID" & _
" INNER JOIN tblResultNotes ON tblResults.ResultID=tblResultNotes.ResultID" & _
"WHERE tblJobs.CreateDate < '" & strDate & "'" & _
"AND tblResults.StartTime < '" & strDate & "'"
Note the date delimiter change to ' instead of #.

SQL Query in MS Access VBA

This query in the form-Data-Record Source is working fine, returning exact values that i want
SELECT tblRevRelLog_Detail.RevRelTrackingNumber, tblRevRelLog_Detail.PartNumber, tblRevRelLog_Detail.ChangeLevel, tblRevRelLog_Detail.Version, tblRevRelLog_Detail.JobPnType, tblRevRelLog_Detail.EdsName, tblRevRelLog_Detail.DetailerNamePerPartNumber, tblRevRelLog_Detail.DetailerCompanyPerPartNumber
FROM tblRevRelLog_Detail
LEFT JOIN tblEventLog ON tblRevRelLog_Detail.PartNumber = tblEventLog.PartNumber
WHERE (((tblEventLog.PartNumber) Not In
(SELECT tblEventLog.PartNumber
FROM tblEventLog
WHERE tblEventLog.EventTypeSelected = 'pn REMOVED From Wrapper'
AND tblEventLog.TrackingNumber = tblRevRelLog_Detail.RevRelTrackingNumber)))
ORDER BY tblRevRelLog_Detail.PartNumber;
But if i write the same query in the VBA. It is not returning anything
strNewSql = "SELECT tblRevRelLog_Detail.PartNumber, tblRevRelLog_Detail.ChangeLevel, tblRevRelLog_Detail.ID FROM tblRevRelLog_Detail LEFT JOIN tblEventLog ON tblRevRelLog_Detail.PartNumber = tblEventLog.PartNumber"
strNewSql = strNewSql & " WHERE ((tblEventLog.PartNumber) Not In (SELECT tblEventLog.PartNumber FROM tblEventLog WHERE tblEventLog.EventTypeSelected = 'pn REMOVED From Wrapper' AND tblEventLog.TrackingNumber = tblRevRelLog_Detail.RevRelTrackingNumber);"
Something wrong with the query?? can someone help me!
I would suspect that your variable tempTrackingNumber is bad
If RevRelTrackingNumber is numeric you don't need to enclose it in quotes.
What's the data type of tempTrackingNumber? Your code (front-truncated) shows this:
...tblRevRelLog_Detail.RevRelTrackingNumber = """ & tempTrackingNumber & """);"
This implies that it's a String, and it will be treated as such.
If it's actually numeric, you'll want this instead:
...tblRevRelLog_Detail.RevRelTrackingNumber = " & tempTrackingNumber & ");"
First, the queries are not the same. For example, your plaintext SQL has eight columns in the SELECT clause where the VBA version has just three.
Second, you are using the same table name, tblEventLog, twice in the same scope. So you will need to use at least one table correlation name. I know the tbl- prefix is a 'point of pride' in the Access world but it does make you table names longer and harder to read IMO (and prefixes are specifically outlawed by the ISO 11179 Standard for data element naming :))... so why not use table correlation names throughout?
Third, IIRC EXISTS performs better than IN for Access (ACE/Jet/whatever) and IMO is easier to understand (DISTINCT..INNER JOIN may perform even better but is again harder to read, IMO).
Here's a suggested re-write:
SELECT D1.PartNumber, D1.ChangeLevel,
D1.ID
FROM tblRevRelLog_Detail AS D1
LEFT OUTER JOIN tblEventLog AS E1
ON D1.PartNumber = E1.PartNumber
WHERE NOT EXISTS (
SELECT *
FROM tblEventLog AS E2
WHERE E2.EventTypeSelected = 'pn REMOVED From Wrapper'
AND E2.TrackingNumber = D1.RevRelTrackingNumber
AND E2.PartNumber = E1.PartNumber
);
UPDATE: Seems I was wrong about the EXIST giving being better, so here's a couple more rewrite to choose from:
SELECT D1.PartNumber, D1.ChangeLevel,
D1.ID
FROM tblRevRelLog_Detail AS D1
LEFT OUTER JOIN tblEventLog AS E1
ON D1.PartNumber = E1.PartNumber
WHERE E1.PartNumber NOT IN
(
SELECT E2.PartNumber
FROM tblEventLog AS E2
WHERE E2.EventTypeSelected = 'pn REMOVED From Wrapper'
AND E2.TrackingNumber = D1.RevRelTrackingNumber
);
Actually, I'm struggling to get this re-writes using Access's proprietary joins. I keep getting a "Catastrophic failure" error. Here's the repro code, where am I going wrong?:
Sub grjieopgj()
On Error Resume Next
Kill Environ$("temp") & "\DropMe.mdb"
On Error GoTo 0
Dim cat
Set cat = CreateObject("ADOX.Catalog")
With cat
.Create _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & _
Environ$("temp") & "\DropMe.mdb"
With .ActiveConnection
Dim Sql As String
Sql = _
"CREATE TABLE tblRevRelLog_Detail " & vbCr & "(" & vbCr & _
" PartNumber VARCHAR(20), " & vbCr & " EventTypeSelected VARCHAR(20), " & vbCr & _
" TrackingNumber VARCHAR(20), " & vbCr & " RevRelTrackingNumber VARCHAR(20), " & vbCr & _
" ChangeLevel VARCHAR(20), ID VARCHAR(20)" & vbCr & ");"
.Execute Sql
Sql = _
"CREATE TABLE tblEventLog " & vbCr & "(" & vbCr & _
" PartNumber VARCHAR(20), " & vbCr & " EventTypeSelected VARCHAR(20), " & vbCr & _
" TrackingNumber VARCHAR(20), " & vbCr & " RevRelTrackingNumber VARCHAR(20), " & vbCr & _
" ChangeLevel VARCHAR(20), ID VARCHAR(20)" & vbCr & ");"
Sql = _
"SELECT DISTINCT D1.PartNumber, D1.ChangeLevel," & _
" " & vbCr & " D1.ID " & vbCr & " FROM (" & vbCr & " tblRevRelLog_Detail" & _
" AS D1" & vbCr & " LEFT OUTER JOIN tblEventLog" & _
" AS E1" & vbCr & " ON D1.PartNumber = E1.PartNumber" & vbCr & "" & _
" )" & vbCr & " LEFT OUTER JOIN tblEventLog" & _
" AS E2" & vbCr & " ON AND E2.TrackingNumber" & _
" <> D1.RevRelTrackingNumber" & vbCr & " " & _
" AND E2.PartNumber <> E1.PartNumber" & vbCr & " WHERE" & _
" E2.EventTypeSelected = 'pn REMOVED From" & _
" Wrapper';"
Dim rs
Set rs = .Execute(Sql)
MsgBox rs.GetString
End With
Set .ActiveConnection = Nothing
End With
End Sub
Seems like you missing a closing bracket. Add ")" at the end of the query in VBA and try.