MS Access VB SQL Syntax for 3 Table Join - sql

I have been trying to create a form which contains information from 3 tables. On this form I would like to have a filter combo box so that the user may select a member type and it will filter the list to members with that member type.
Members in our database can have more than one type. For this reason I created a memberTable:
MemberID
FName
SName
etc.
A membertype table:
MemberTypeID
MemberTypeName
and a joining table membermembertype:
MemberID
MemberTypeID
I have tried to set my form up with a number of different queries:
SELECT qryMemberType.MemberID, qryMemberType.FName, qryMemberType.SName,
qryMemberType.MemberTypeName, qryMemberType.MemberTypeID FROM qryMemberType;
SELECT [member].[MemberID] AS [member_MemberID], [member].[FName], [member].[SName],
[membertype].[MemberTypeID] AS [membertype_MemberTypeID], [membertype].[MemberTypeName],
[membermembertype].[MemberID] AS [membermembertype_MemberID], [membermembertype].[MemberTypeID]
SELECT [member].[MemberID] AS [member_MemberID], [member].[FName], [member].[SName],
[membermembertype].[MemberID] AS [membermembertype_MemberID],
[membermembertype].[MemberTypeID] AS [membermembertype_MemberTypeID],
[membertype].[MemberTypeID] AS [membertype_MemberTypeID]
The VBA for the combo box that I have been attempting to filter with is:
Dim myMember As String
myMember = "SELECT ... FROM ... WHERE ([MemberTypeID] = " & Me.cboMemberType & ");"
Me.frmFilterTestSub.Form.RecordSource = myMember
Me.frmFilterTestSub.Form.Requery
I have tried numerous different syntaxes for the SELECT statement in the VBA for the combo box including:
"Select * from membermembertype where ([MemberTypeID] = " & Me.cboMemberType & ")"
"SELECT member.MemberID AS member_memberID, member.FName, member.SName,
membertype.MemberTypeID AS membertype_MemberTypeID, membertype.MemberTypeName,
membermembertype.MemberID AS membermembertype_MemberID,
membermembertype.MemberTypeID AS membermembertype_MemberTypeID
FROM member
LEFT JOIN (membertype
RIGHT JOIN membermembertype ON membertype.[MemberTypeID] = membermembertype.[MemberTypeID])
ON member.[MemberID] = membermembertype.[MemberID]
WHERE ([MemberTypeID] = " & Me.cboMemberType & ")"
"SELECT member.*,
(membermembertype.MemberID AS mmt_MemberID),
(membermembertype.MemberTypeID AS mmt_MemberTypeID),
membertype.MemberTypeName
FROM (member
LEFT JOIN membermembertype ON mmt_MemberID = (member.MemberID AS m_MemberID))
RIGHT JOIN membertype ON mmt_MemberTypeID=(membertype.MemberTypeID AS mt_MemberTypeID)
WHERE ([MemberTypeID] = " & Me.cboMemberType & ");"
I'm pretty sure the first example returned the closest result with the list returning the correct number of records for each member type selected, however the fields were filled with the #Name? error value which is why I was trying to do a number of different ways to join the tables. The other SELECT STATEMENTS are returning SQL Syntax errors.
Any advice would be greatly appreciated!

Since you only want to list the members, I guess that you are not really interested with membertype table info, then you can simply do this :
"SELECT member.MemberID AS member_memberID, member.FName, member.SName
FROM member
INNER JOIN membermembertype
ON (membermembertype.[MemberTypeID] = " & Me.cboMemberType & " AND member.[MemberID]=membermembertype.[MemberID]) "

Right outer join is highly frowned on in SQL, when you can use a left outer join in the correct order instead.
In your case, inner joins are better anyway.
You should use a parameter rather than string concatenation if you care about security, but since you're using Access I guess anyone with access to the file can already do what they like.
Please try this one and let me know if you get an error.
SELECT [Member].MemberId
, [Member].FName
, [Member].SName
, [MemberType].MemberTypeId
, [MemberType].MemberTypeName
FROM ((MemberType
INNER JOIN MemberMemberType ON MemberMemberType.MemberTypeId = MemberType.MemberTypeId)
INNER JOIN Member ON Member.MemberId = MemberMemberType.MemberId)
WHERE MemberType.MemberTypeId = 123 --Put your parameter here once you've tested that it works for a specific value

Related

Complex JOINS in Access SQL difficult to convert to JET OLEDB

I'm a long time follower of Stack overflow but this is my first post. I'm hoping the community can help.
I have a successful Access Query that returns the required results - Perfect!
HOWEVER, I'm trying to return the same using OLEDB connection to the database within an ASP script. This is all legacy stuff however we are allowing web access to this legacy information.
MS Access (2016) shows Query as this... (works)
SELECT [EventName] & ": " & [RoundCaption] AS RoundTitle, ChunkEntryTable.WinPos
FROM ((EventTable INNER JOIN EventRoundTable ON EventTable.EventId = EventRoundTable.EventId) INNER JOIN ((RoundHeatTable INNER JOIN ChunkTable ON RoundHeatTable.RoundHeatId = ChunkTable.RoundHeatId) INNER JOIN (EventEntryTable INNER JOIN ChunkEntryTable ON EventEntryTable.EventEntryId = ChunkEntryTable.EventEntryId) ON ChunkTable.ChunkId = ChunkEntryTable.ChunkId) ON EventRoundTable.RoundKeyId = RoundHeatTable.RoundKeyId) LEFT JOIN EventEntryMemberTable ON EventEntryTable.EventEntryId = EventEntryMemberTable.EventEntryId
WHERE (((EventEntryTable.Entry1Id)=[EntryId])) OR (((EventEntryTable.Entry2Id)=[EntryId])) OR (((EventEntryTable.Entry3Id)=[EntryId])) OR (((EventEntryMemberTable.MemberId)=[EntryId]))
ORDER BY EventTable.SortIdx, EventRoundTable.RoundId DESC , EventRoundTable.IsRepechage DESC;
Doing this in OLEDB. Connection string as follows...
<%
' FileName="Connection_ado_conn_string.htm"
' Type="ADO"
' DesigntimeType="ADO"
' HTTP="true"
' Catalog=""
' Schema=""
Dim MM_csresultdb_STRING
MM_csresultdb_STRING = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=xyz.mde;Jet OLEDB:Database Password=xxxxxxxxx;"
%>
Connection works perfectly but I can't seem to get the SQL command to work. I get "No value given for one or more required parameters".
NOTE: I have replaced [EntryID] in 4 places with a valid value and it works perfectly in Access just not outside of Access using OLEDB. Here's what the SQL is I'm using...
SELECT EventTable.EventName & ": " & EventRoundTable.RoundCaption AS RoundTitle, ChunkEntryTable.WinPos FROM
((EventTable INNER JOIN EventRoundTable ON EventTable.EventId = EventRoundTable.EventId) INNER JOIN
((RoundHeatTable INNER JOIN ChunkTable ON RoundHeatTable.RoundHeatId = ChunkTable.RoundHeatId) INNER JOIN
(EventEntryTable INNER JOIN ChunkEntryTable ON EventEntryTable.EventEntryId = ChunkEntryTable.EventEntryId) ON ChunkTable.ChunkId = ChunkEntryTable.ChunkId) ON ChunkTable.ChunkId = ChunkEntryTable.ChunkId)
ON EventRoundTable.RoundKeyId = RoundHeatTable.RoundKeyId)
WHERE ((EventEntryTable.Entry1Id)=4741) OR ((EventEntryTable.Entry2Id)=4741) OR ((EventEntryTable.Entry3Id)=4741)
ORDER BY EventTable.SortIdx, EventRoundTable.RoundId DESC , EventRoundTable.IsRepechage DESC;
FOUND PROBLEM ** See answer below
FOUND PROBLEM ** It's to do with this part of the SQL...
[EventName] & ": " & [RoundCaption] AS RoundTitle
Changed to
[EventName], [RoundCaption] AS RoundTitle
and it works but gives me two separate fields rather than the one concatenated field called "RoundTitle". So I'll join the two result fields during the display output rather than at the query stage.
Whew! That many days to figure out. Thanks to the comments that kinda steered me in that direction of the AS part of the statement.

ConcatRelated() - query or tables

I have similar issue to this question Combine values from related rows into a single concatenated string value.
I've got two queries:
This is what it looks like now without ConcatRelated():
I need to get return:
I tried to use this SQL:
SELECT DISTINCT
Q_Fakt1.FakturaID,
Q_Fakt1.DatumVystavenia,
Q_Fakt1.DatumSplatnosti,
Q_Fakt2.Pismeno,
ConcatRelated(
"pismeno",
"Q_Fakt2",
"FakturaID = '" & [Q_Fakt1]![FakturaID] & "'"
) AS Letters
FROM Q_Fakt1 INNER JOIN Q_Fakt2 ON Q_Fakt1.FakturaID = Q_Fakt2.FakturaID;
Result is 7× popup:
ConcatRelated() Error3464: Data type mismatch in criteria expression.
I did the same with Tables but I have little bit more complicated Relations so...
https://i.stack.imgur.com/TM7Cu.png
SQL:
SELECT DISTINCT
Faktury.FakturaID,
Kategorie.Oznacenie,
Faktury.DatumVystavenia,
FakturujemVam.FakturujemVamID,
FakturyDetaily.FakturujemVam,
[DatumVystavenia]+[splatnostFaktury] AS DatumSplatnosti,
ConcatRelated("Oznacenie","kategorie","FakturaID = '" & [FakturaID] & "'") AS Letters
FROM Kategorie INNER JOIN (Faktury INNER JOIN (FakturujemVam INNER JOIN FakturyDetaily ON FakturujemVam.FakturujemVamID = FakturyDetaily.FakturujemVam) ON Faktury.FakturaID = FakturyDetaily.Faktura) ON Kategorie.KategoriaID = FakturujemVam.Kategoria;
Result is 6× popup:
ConcatRelated() Error3061: Too Few parameters. Excepted 1.
Where did I go wrong? Thank you for Help
That's because you're using string delimiters when you're not using a string.
Remove those delimiters, and it will work fine:
ConcatRelated("Oznacenie","kategorie","FakturaID = " & [FakturaID] ) AS Letters
SOLVED:
STEP 1
Create Query to merge more tables in one
Datasheet View
Design View
STEP 2
Create another Query & Use ConcatRelated()
Design View
SQL:
SELECT
Q_Part_Bill_Num2.NumBill,
Q_Part_Bill_Num2.C_Mark,
ConcatRelated(
"C_Mark",
"Q_Part_Bill_Num2",
"Q_Part_Bill_Num2!NumBill = " & [Q_Part_Bill_Num2]![NumBill]
) AS PartBillNum2
FROM Q_Part_Bill_Num1 INNER JOIN Q_Part_Bill_Num2 ON Q_Part_Bill_Num1.NumBill = Q_Part_Bill_Num2.NumBill;
STEP 3 - Optional
Edit MODULE to delete / change separator ", "
STEP 4
Create One Last Query to Concatenate everything together.
Design View
SQL:
SELECT DISTINCT
Q_Part_Bill_Num1.PartBillNum1,
Q_Part_Bill_Num3.PartBillNum2,
[PartBillNum1] & [PartBillNum2] AS [Full]
FROM
(T_Bills INNER JOIN Q_Part_Bill_Num1 ON T_Bills.Bills_ID = Q_Part_Bill_Num1.Bills_ID)
INNER JOIN (Q_Part_Bill_Num2 INNER JOIN Q_Part_Bill_Num3
ON (Q_Part_Bill_Num2.NumBill = Q_Part_Bill_Num3.NumBill)
AND (Q_Part_Bill_Num2.C_Mark = Q_Part_Bill_Num3.C_Mark))
ON Q_Part_Bill_Num1.NumBill = Q_Part_Bill_Num2.NumBill;
Use DISTINCT to avoid duplicates.
I Hope this will help someone.
Thank you all, for your time :)

MS Access VBA Add Decimals to Output

I have data which have 2 decimal places (See Figure) and am using the function to subtract the two values but I'm getting a rounded number as my output. I've tried to add float to the following expression "(L.M123_Corr_Integrator-R.M123_Corr_Integrator)" but it's throwing out an error. I'm not familiar with sql/vba code so any useful information would help.
sql = "UPDATE (SELECT R.DateLog , ( L.M123_Corr_Integrator - R.M123_Corr_Integrator) AS Gross " & _
"FROM tbl_M123_DataSet AS L INNER JOIN tbl_M123_DataSet AS R " & _
"ON L.DateLog = DATEADD('d', 1, R.DateLog)) as T " & _
"INNER JOIN tbl_M123_DataSet ON tbl_M123_DataSet.DateLog = T.DateLog " & _
"Set Gross_kWh = Gross"
dbs.Execute sql, dbFailOnError
MsgBox dbs.RecordsAffected & " rows affected on column GrossKW"
That query unobfuscated looks like this:
UPDATE
(
SELECT
R.DateLog,
L.M123_Corr_Integrator - R.M123_Corr_Integrator AS Gross
FROM
tbl_M123_DataSet AS L
INNER JOIN tbl_M123_DataSet AS R
ON L.DateLog = DATEADD('d', 1, R.DateLog)
) AS T
INNER JOIN tbl_M123_DataSet
ON tbl_M123_DataSet.DateLog = T.DateLog
SET Gross_kWh = Gross
It looks to me that you have the table field Gross_kWh set to integer. In the table design view, highlight the row Gross_kWh and set its number type to 'Double'.
Also be aware that Access will sometimes round numbers for display, but the decimal accurate number is stored in the table correctly.

Another Syntax error (missing operator) in query expression

I need a little help developing my SQL query. My goal is to remove an entry. My condition is two tables away. I've gotten this far but I can't seem to find where the other mistake
con.Execute "DELETE FROM Expenses INNER JOIN Agreements ON Agreements.AgreementsID =
Expenses.AgreementID AND INNER JOIN Audits
ON Audits.AuditID = Agreements.AuditID WHERE Audits.Share = True"
I'm using access 2007 and my con variable is
con.Open _
"Driver={Microsoft Access Driver (*.mdb, *.accdb)};" & _
"Dbq=" & Loc & ";"
Try This, You are using AND before INNER JOIN, remove that only.
DELETE DISTINCTROW Expenses.*
FROM Expenses
INNER JOIN Agreements ON Agreements.AgreementsID = Expenses.AgreementID
INNER JOIN Audits ON Audits.AuditID = Agreements.AuditID
WHERE Audits.Share = True
[EDIT Query]
DELETE Expenses.*
FROM Expenses
WHERE Expenses.AgreementID IN (
SELECT Agreements.AgreementID FROM Agreements
INNER JOIN Audits ON Audits.AuditID = Agreements.AuditID
WHERE Audits.Share = True
)
OP get error:- Too few parameters Expected 2.
To handle this, This error may be obtained because the any column names being selected have special characters in it. If there are special characters in the column names of the database, the name should be surrounded with brackets in the SQL query. So if you have any column name which have special char value , then try [ColumnName]

Syntax Error in Join Operation in MS-Access when splitting and comparing records

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.