This sounds ridiculously easy but I've tried so many different approaches. This query is just set up weird and I'm trying to JOIN it but there's not a common column I can do that with. There is, however, a LastFirst column (consists of LastName then FirstName) written in the context of DOE, JOHN. Then on the columns I'm trying to join that with it's just FirstName (John) and LastName (Doe).
I'm actually trying to select data from 4 tables that all are returning 1 row. These 2 tables can be joined:
SELECT
RIFQuery.*,
_Employee.EmployeeLastName + ', ' + _Employee.EmployeeFirstName AS EmployeeLastFirst,
_Employee.EmployeeTitle, _Employee.Phone As EmployeePhone,
_Employee.EmailAddress As EmployeeEmailAddress
FROM
RIFQuery
INNER JOIN
_Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE
RIFQuery.Autonumber = 1
This one has nothing to join with so I'll probably union it and null remaining columns:
SELECT *
FROM tblOrganization
This is the table that contains LastName and FirstName that I'm trying to join with RIFQuery.LastFirst:
SELECT
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM
_Clients
WHERE
_Clients.LASTNAME = left(RIFQuery.LastFirst, len(RIFQuery.LastFirst)-CHARINDEX(',', REVERSE(RIFQuery.LastFirst)))
AND _Clients.FIRSTNAME = ltrim(substring(RIFQuery.LastFirst, len(RIFQuery.LastFirst)-CHARINDEX(',', REVERSE(RIFQuery.LastFirst))+2, len(RIFQuery.LastFirst)))
In that WHERE statement the code will split the LastFirst column and get the row by searching their LastName and FirstName. I'm wondering if there's a way I can write that into a JOIN? Otherwise I can probably UNION and null remaining columns but it will look very ugly.
UPDATE
I tried 2 suggestions from here and both result in a syntax error. I forgot to mention that I'm executing this code inside Microsoft Access VBA and trying to retrieve a DAO.RecordSet. I had to remove some table names in the SELECT statement to get past a syntax error from there, so maybe I should update the question to reflect MS ACCESS and not SQL Server, although only the query is the only pure Access object and the rest are linked ODBC tables to SQL Server.
UPDATE
Just one of those issues where I can't sleep until it's fixed and will obsess until it is. If I take out all _Employee references (from SELECT and JOIN statements), it wants to work but errors about too few parameters. I just now know this is related to _Employee. Getting different results from applying parentheses and just hoping I'll get lucky and hit on it.
The error is caused by this line:
INNER JOIN [_Employee] ON [_Employee].[AutoNumber] = [RIFQuery].[CreatedBy]
I get this error:
"Syntax error (missing operator) in query expression".
As seen in this screenshot:
Here's my latest query I'm playing with, minus the parentheses:
str = "SELECT [RIFQuery].*, " & vbCrLf & _
" ([_Employee].[EmployeeLastName] & ', ' & [_Employee].[EmployeeFirstName]) AS [EmployeeLastFirst], " & vbCrLf & _
" [_Employee].[EmployeeTitle], " & vbCrLf & _
" [_Employee].[Phone] AS [EmployeePhone], " & vbCrLf & _
" [_Employee].[EmailAddress] AS [EmployeeEmailAddress], " & vbCrLf & _
" [_Clients].[Gender] AS [ClientGender], " & vbCrLf & _
" [_Clients].[DOB] AS [ClientDOB], " & vbCrLf & _
" [_Clients].[SSN] AS [ClientSSN] " & vbCrLf & _
"FROM [_Clients] " & vbCrLf & _
" INNER JOIN [RIFQuery] ON [RIFQuery].[LastFirst] = [_Clients].[LASTNAME] & ', ' & [_Clients].[FIRSTNAME] " & vbCrLf & _
" INNER JOIN [_Employee] ON [_Employee].[AutoNumber] = [RIFQuery].[CreatedBy] " & vbCrLf & _
"WHERE [RIFQuery].[Autonumber] = 1;"
For debugging purposes, if I remove those last 2 lines and the _Employee SELECT statements, it'll process the query without a problem. If anyone has any ideas just let me know.
I was focused on that RIFQuery JOIN statement being the culprit for the longest time but I've found that simply is not the issue any more. With that said, this thread has been essentially solved and I appreciate the help.
MS Access is using a slightly different syntax than SQL Server when it comes to using more than one JOIN. You could leave out the JOIN with the _Clients (making it a cross join) and move that condition to the WHERE clause, which would make the query look like this (and which would allow you to display the design window for the query without any problem)
SELECT RIFQuery.*,
EmployeeLastName + ', ' + EmployeeFirstName As EmployeeLastFirst,
EmployeeTitle, Phone As EmployeePhone, EmailAddress As EmployeeEmailAddress,
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM _Clients, RIFQuery INNER JOIN _Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE RIFQuery.LastFirst = _Clients.LASTNAME & ", " & _Clients.FIRSTNAME;
Instead of assembling the query string in VBA just for being able to change the parameter value, I suggest to save the following query as an Access object (maybe qryRIF):
PARAMETERS lgRIF Long;
SELECT RIFQuery.*,
EmployeeLastName + ', ' + EmployeeFirstName As EmployeeLastFirst,
EmployeeTitle, Phone As EmployeePhone, EmailAddress As EmployeeEmailAddress,
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM _Clients, RIFQuery INNER JOIN _Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE RIFQuery.LastFirst = _Clients.LASTNAME & ", " & _Clients.FIRSTNAME
AND RIFQuery.Autonumber = [lgRIF];
In your VBA code, you can use code like the following to grab the QueryDef object, assign the parameter value and open a recordset:
With CurrentDb.QueryDefs!qryRIF
!lgRIF = lgRIF
With .OpenRecordset()
' ... your code ...
.Close
End With
.Close
End With
Related
I have been trying to run a query from MS ACCESS VBA. My query works well when I don't add concatenated fields. When I use a concatenated field like in the code below, it turns an empty result.
Is there any work around?
lstStudentName.RowSource = "SELECT [sdtName] & ' ' & [sdtFatherName] & ' ' & [sdtLastName] AS sdtFullName, sdtID FROM tbl_sdt_Info " & _
" LEFT join tbl_sdt_Rounds ON tbl_sdt_Info.sdtID = tbl_sdt_Rounds.sdtID " & _
" WHERE IS NULL(tbl_sdt_Rounds.sdtID)"
Issues with your SQL:
Incorrect use of IS NULL - should be either IsNull(tbl_sdt_Rounds.sdtID) or tbl_sdt_Rounds.sdtID IS NULL. The latter is preferable because it is SQL, IsNull() is a VBA function.
Since there are two sdtID fields, query shouldn't work without table prefix to specify field. I am surprised you get anything.
Although possibly not an issue as is, my preference would be to make sdtID the first field and set ColumnWidths as 0";1.0" and first column as BoundColumn. This will allow viewing and typing first letter of name but sdtID will be listbox value.
Never hurts to build and test query object and when it works, replicate SQL statement in VBA.
lstStudentName.RowSource = "SELECT tbl_sdt_Info.sdtID, sdtName & ' ' & sdtFatherName & ' ' & sdtLastName AS sdtFullName FROM tbl_sdt_Info " & _
"LEFT join tbl_sdt_Rounds ON tbl_sdt_Info.sdtID = tbl_sdt_Rounds.sdtID " & _
"WHERE tbl_sdt_Rounds.sdtID IS NULL;"
I'm trying to attach a SELECT query to a VBA object in Access, but I keep getting the error:
Syntax Error in Join operation
Dim sql As String
sql = "SELECT R_History.iteration, R.RuntimeID, Policylanguage.FormBody " & _
"FROM PolicyLanguage " & _
"INNER JOIN ([Policy&Elements] " & _
"INNER JOIN ((R " & _
"INNER JOIN R_History " & _
"ON (R.RunTimeID = R_History.RunTimeID " & _
"AND (R.ReportID = R_History.ReportID)) " & _
"INNER JOIN StatePolicyLanguage " & _
"ON R_History.Iteration = StatePolicyLanguage.Iteration) " & _
"ON [Policy&Elements].[Text&ElementID] = StatePolicyLanguage.[TextID&ElementID] " & _
"ON PolicyLanguage.TextID = [Policy&Elements].TextID " & _
"WHERE (((R.RuntimeID) = Dlast('runtimeID','r')));"
DoCmd.RunSQL (sql)
I can't get this to run for the absolute life of me. Can anyone tell what's wrong?
Edit: Here is the code I am trying to emulate
If you're running a query where the criteria are values entered in a form (e.g. field1 = frm1.txtValue), you could create a parameterized query where the passed parameters are added to the WHERE clause. That way, you don't have create SQL in VBA---you'd just have to set the parameters in VBA.
As noted by others, Access requires you to put parentheses after each join:
from (((Table1
inner join Table2 on Table2.field1 = Table1.field1)
inner join Table3 on Table3.field2 = Table2.field2)
inner join Table4 on Table4.field3 = Table3.field3)
So, as suggested by others, if you absolutely need to construct the query via VBA, keep your JOIN and ON clauses together to prevent confusion, and add the necessary parentheses.
I've found when you have to create complex queries in Access (either in the SQL editor or in VBA), it can be helpful to write the SQL in a more friendly editor (e.g. Notepad++) that supports things like syntax highlighting. Then, you can paste the query where it needs to go.
I am executing SQL in VB6 and this is the string that I am using, where I define currFA as a number 1. I've been debugging and working at this since it's using inner joins and unions (it's a query I made in Access that I am trying to put into VB6 to run). Right now, I'm getting an operator missing error on the run.
sql = "SELECT DISTINCT [~ALLCBLEQ].Equipment, [~FIRE_AREAS].INDEX" _
& "FROM ([~FIRE_AREAS] INNER JOIN [~ALLTARGETS] ON [~FIRE_AREAS].FULL_ID = [~ALLTARGETS].FA) INNER JOIN ([~ALLRWCBL] INNER JOIN [~ALLCBLEQ] ON" _
& "[~ALLRWCBL].Cable = [~ALLCBLEQ].Cables) ON [~ALLTARGETS].TARGET = [~ALLRWCBL].Cable" _
& "WHERE ((([~FIRE_AREAS].INDEX) = '" & currFA & "'))" _
& "UNION" _
& "SELECT DISTINCT [~ALLCBLEQ].Equipment, [~FIRE_AREAS].INDEX" _
& "FROM [~FIRE_AREAS] INNER JOIN (([~ALLTARGETS] INNER JOIN [~ALLRWCBL] ON [~ALLTARGETS].TARGET=[~ALLRWCBL].Raceway) INNER JOIN [~ALLCBLEQ] ON" _
& "[~ALLRWCBL].Cable=[~ALLCBLEQ].Cables) ON [~FIRE_AREAS].FULL_ID=[~ALLTARGETS].FA" _
& "WHERE ((([~FIRE_AREAS].INDEX) = '" & currFA & "'));"
Any help on the error and syntax improvement tips are greatly appreciated! Still learning!
Thanks!
Your string has no spaces between the lines so when you write:
sql = "SELECT DISTINCT [~ALLCBLEQ].Equipment, [~FIRE_AREAS].INDEX" _
& "FROM ([~FIRE_AREAS] …
That becomes a SQL string like
SELECT DISTINCT [~ALLCBLEQ].Equipment, [~FIRE_AREAS].INDEXFROM ([~FIRE_AREAS] …
Which is obviously invalid SQL because there's no space between INDEX and FROM.
An easy solution is just to put a space before each closing quote (or after each open quote):
sql = "SELECT DISTINCT [~ALLCBLEQ].Equipment, [~FIRE_AREAS].INDEX " _
& "FROM ([~FIRE_AREAS] …
However, If you find yourself writing relatively complex queries like this, I would recommend that you consider converting them to stored procedures or views instead.
Above error message occurs with this statement:
SELECT f.fullname INTO SummaryJudgment_FinalForgottenWithMiddle
FROM (
(SELECT Left([aname],InStr(1,[aname],",")-1)) As lastname FROM
SummaryJudgment_FinalForgotten) & " " & (SELECT
RIGHT([aname],InStr(1,[aname],",")+1)) As firstname FROM
SummaryJudgment_FinalForgotten) & " " & (SELECT
summary_judgment.middle_initial AS middlename FROM summary_judgment)
) AS fullname
FROM SummaryJudgment_FinalForgotten AS f INNER JOIN summary_judgment
AS s ON f.lastname = s.last_name && f.firstname = s.first_name;
Basically this is what two tables look like (note they will have more fields than 1 where last or first name of different fields can be similar):
SummaryJudgment_FinalForgotten (table)
aname (field)
Leventhal,Raymond (data)
summary_judgment (table)
first_name(field)
Raymond (data)
last_name (field)
Leventhal (data)
middle_initial (field)
P (data)
Ultimately, I'm trying to create a new table that is like
SummaryJudgment_FinalForgotten but with the middle initial from
summary_judgment appended:
Leventhal,Raymond P
You do not need to write 3 select statements to concatenate the values into one field.
select left(...) & right(...) & initial AS fullname INTO SummaryJudgment_FinalForgottenWithMiddle
FROM SummaryJudgment_FinalForgotten
Are you trying to use two ampersands to represent a logical AND?
FROM SummaryJudgment_FinalForgotten AS f INNER JOIN summary_judgment
AS s ON f.lastname = s.last_name && f.firstname = s.first_name;
I don't think that's legal for Access' Jet/ACE database engines. Try it with the AND keyword in place of &&.
OTOH, I wonder if you can do something simpler.
SELECT last_name & "," & first_name & " " & middle_initial AS fullname
INTO SummaryJudgment_FinalForgottenWithMiddle
FROM summary_judgment;
This works:
SELECT left([aname],InStr(1,[aname],",")-1) & " "
& right([aname],Len(aname)-InStr(1,[aname],",")) & " "
& summary_judgment.middle_initial AS fullname
INTO SummaryJudgment_FinalForgottenWithMiddle
FROM SummaryJudgment_FinalForgotten, summary_judgment;
Though you might want this instead:
SELECT left([aname],InStr(1,[aname],",")-1) & ", "
& right([aname],Len(aname)-InStr(1,[aname],",")) & " "
& summary_judgment.middle_initial AS fullname
INTO SummaryJudgment_FinalForgottenWithMiddle
FROM SummaryJudgment_FinalForgotten, summary_judgment;
The second version gives you the comma after the last name. Note that Right counts from the right, which is why you have to subtract the InStr value from the length.
EDIT:
The code I gave above works with your sample data--one row in each table. With more rows, it gives a cross product of (LastName, FirstName) x MiddleInitial. It occurred to me that that might be the case, so I went back to my test & added a second row--it is true. So then I tried to write the join expression....
Access doesn't like this:
... ON left([aname],InStr(1,[aname],",")-1) = last_name ...
It throws the error "Join expression not supported." Changing it to this:
... ON (trim((left(SummaryJudgment_FinalForgotten.aname,InStr(1,[aname],",")-1))=trim(summary_judgment.last_name))) ...
results in a query that runs & creates the table, but doesn't create any rows (the same was true before I added the "trim" calls in an attempt to fix it).
So I tried specifying the table for all occurences of aname. No joy--until I realized that I was making the wrong comparison (derived-last to last and derived-first to last--oops).
Using the following FROM clause with either above SELECT ... INTO does work correctly:
FROM
SummaryJudgment_FinalForgotten INNER JOIN
summary_judgment ON
((left(SummaryJudgment_FinalForgotten.aname,InStr(1,SummaryJudgment_FinalForgotten.[aname],",")-1))=summary_judgment.last_name) AND
((right(SummaryJudgment_FinalForgotten.aname,Len(SummaryJudgment_FinalForgotten.aname)-InStr(1,SummaryJudgment_FinalForgotten.[aname],","))=summary_judgment.first_name));
It might even work correctly without the full qualification of each field now that I'm joining first to first & last to last (since there is no duplication across the tables), but having proven that it does work, I'm done.
I'm re-writing a small ms-access application to take examinations on.
What they want is for the tests to grab a set of random questions based on how large the exam's size is.
If each exam was a set number of questions, I could just stick the number in the TOP statement and be done with it, but there are a variable number of questions for each exam, so I want to replace the constant number next to the TOP with a field from the query.
What I basically want is like this:
SELECT TOP tblExam.[ExamSize] *
FROM tblExamQuestions INNER JOIN tblExam
ON tblExamQuestions.ExamID = tblExam.ExamID
WHERE tblExam.ExamID = 10
ORDER BY Rnd(tblExamQuestions.ExamQuestionID);
I'm supplying the new ExamID to this query for each exam session when I open the report, so this will probably get in the way.
DoCmd.OpenForm strExamName, , , "tblExam.ExamID = " & strExamID
I think you would have to build the query dynamically.
sSQL="SELECT TOP " & DlookUp("ExamSize","tblExam","ExamID = 10") _
& " FROM tblExamQuestions INNER JOIN tblExam " _
& "ON tblExamQuestions.ExamID = tblExam.ExamID " _
& "WHERE tblExam.ExamID = 10 " _
& "ORDER BY Rnd(tblExamQuestions.ExamQuestionID)"
'' Permanently change an existing query
CurrentDB.QueryDefs("MyReportQuery").SQL=sSQL