MS ACCESS SQL issue with combine LEFT JOINS and INNER JOINS - sql

MS Access has been just killing me when It comes to writing my own SQL queries and I hate it's GUI query tool. I gave up trying to combine LEFT JOINS and INNER JOINS now I'm doing all inner join's and i'm still getting murdered. Can someone link to me to a comprehensible MS Access SQL guide and/ or tell me what I am doing wrong here. I've tried putting my code in parenthesis, bracketing my fields. I'm at my wits end.
SELECT answers.*
FROM (((answers
INNER JOIN caseInfo
ON answers.[ABAWDNum] = caseinfo.[ABAWDNum])
INNER JOIN Questions)
ON answers.[questionID] = questions.[questionID])
INNER JOIN responseCodes
ON answers.[responseIDCode] = responseCodes.[responsecode]
I'm not sure if my picture of the error is coming up but it says Sytnax error in FROM clause and it has the parenthesis right after the Questions table is mentioned
enter image description here
EDIT: Database relationships:
enter image description here

Access INNER JOIN can only work on two data sets at once, so if you want to join more than two tables, you have to nest the INNER JOINS using brackets, as described here:
https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/bb208854(v=office.12)
From that page it says the syntax to do this is...
SELECT fields FROM table1 INNER JOIN (table2 INNER JOIN [( ]table3 [INNER JOIN [( ]tablex [INNER JOIN …)] ON table3.field3compoprtablex.fieldx)] ON table2.field2compoprtable3.field3) ON table1.field1compoprtable2.field2;

I believe this will give you all fields from the table answers that meet your join conditions.
SELECT answers.*
FROM answers
INNER JOIN caseInfo
ON answers.[ABAWDNum] = caseinfo.[ABAWDNum]
INNER JOIN Questions
ON answers.[questionID] = questions.[questionID]
INNER JOIN responseCodes
ON answers.[responseIDCode] = responseCodes.[responsecode]

Just to humor Access I used the GUI/Design mode to build a query.
Here's the query I got that ran. From a table with 674 records, it only returned 6 answers, but that is a separate problem that I have to deal with. At least this thing runs.
But I have a feeling once I start asking for left joins I'm in trouble. <_< F* access.
SELECT answers.*
FROM (Questions
INNER JOIN (CaseInfo
INNER JOIN answers ON CaseInfo.ABAWDNum = answers.ABAWDNum)
ON Questions.questionID = answers.questionID)
INNER JOIN responseCodes ON (Questions.questionID = responseCodes.questionCode)
AND (answers.responseIDCode = responseCodes.responseCode);
EDIT:
I used the GUI/Designer again to try to make a query that was closer to what I needed, which is all of the answers in the answers table plus just a few things from the question table, caseinfo table, and responsecode tables , and this is what I got
SELECT
CaseInfo.ABAWDNum, CaseInfo.Admin, CaseInfo.Unit,
CaseInfo.[ASV-DRV Completed By], CaseInfo.reviewerID, CaseInfo.[Recieved Date],
CaseInfo.[Date Reviewed],
Questions.Question,
answers.responseIDCode, responseCodes.responseDescription, answers.comments
FROM
CaseInfo
RIGHT JOIN
((Questions
RIGHT JOIN
answers ON Questions.questionID = answers.questionID)
LEFT JOIN
responseCodes ON answers.responseIDCode = responseCodes.responseCode)
ON CaseInfo.ABAWDNum = answers.ABAWDNum;
This is really insane. I'm going to have to study this really hard. It looks like access is very particular on how it wants it's joins, but this seems to give me the correct results. 674 records returned.

Related

SQL Statement for Accessing Data from Multiple Tables

I have 7 Tables as per attached following Image.
I will either enter Engine Number or Chassis Number and it should show the respective tables information (these tables have only mentioned fields) so all fields can be shown as result.
I can use hard coded Engine Number or Chassis Number. Every time of execution of this Query, I will hard code the required Engine/Chassis Number and will get the result.
Can anybody please help me to write this query for me?
Click Here to See the Tables
This might be a starting point for your solution.
SELECT prod.EngineNo AS engNo, prod.ChassisNo, doral.doralNo [, table.column [AS name]]
FROM DOProductSpecsDetais AS prod
INNER JOIN DORAL AS doral
ON prod.DOProductSpecsDetailID = doral.DOProductSpecsID
INNER JOIN DOProductDetail AS prodDetail
ON prod.DOProductDetailID = prodDetail.DOProductDetailID
WHERE prod.ChassisNo = '<input>' OR prod.EngineNo='<input>'
Between the SELECT and the FROM Statement, you can select any column out of your JOIN.
You can cascade as many JOINs as you like...
Which DBMS are you going to use?
One suggestion: Try to simplify the names of your columns, if possible.
One more: If you just started to do Database things, it is always helpful to start a test environment and use a client tool.
You can write query something like this:
select * from
DoProductSpecsDetail tbl1 inner join Doral tbl2
on tbl1.DoProductSpecsDetailId = tbl2.DoProductSpecsId
inner join DoproductDetail tbl3
on tbl1.DoProductDetailId = tbl3.DoProductDetailId
inner join ProductColor tbl4
on tbl1.ProductColorId = tbl4.ProductColorId
inner join DoDetail tbl5
on tbl3.DeliveryOrderDetailId = tbl5.DeliveryOrderId
inner join ProductMain tbl6
on tbl3.ProductId = tbl6.ProductId
inner join BPMain tbl7
on tbl5.BusinessPartnerId = tbl7.BusinessPartnerId

Explanation of SQL ON

I have been googled some for an explanation of the SQL function ON though
I couldn't find a good explanation how it work.
is it associated/connected to INNER JOIN?
Could someone please explain my Code-snippet what really happens?
(see my code below)
SELECT
TS_TEST_ID as Test_ID,
TS_NAME as Name
FROM TEST
INNER JOIN DESSTEPS
ON TEST.TS_TEST_ID = DESSTEPS.DS_TEST_ID
INNER JOIN ALL_LISTS
ON ALL_LISTS.AL_ITEM_ID = TEST.TS_SUBJECT
It is not a function, it is part of language. Like with natural language you have various types of words: like nouns, verbs etc. This is like proposition.
ON is a part of syntax for INNER JOIN, it goes like this:
one table INNER JOIN some other table ON how do I want to join both tables (key columns)
You might find some more details here
on tells the join with which condition the tables should be connected.
In this case:
FROM TEST
INNER JOIN DESSTEPS
ON TEST.TS_TEST_ID = DESSTEPS.DS_TEST_ID
You tables test will be joined on column TS_TEST_ID and DS_TEST_ID. So records belong together, where These id's are equals

Is it possible to detect where the join fails on a certain record?

Please bear with me as this may be a question without a possible answer, but I hope I describe it correctly..
I have a query which joins a number of tables and produces results, and here is the SQL:
SELECT
dbo.Property.PropertyPK,
dbo.Tenancy.TenancyPK,
dbo.Tenant.ContactFK,
dbo.Contacts.strTitle,
dbo.Contacts.strFirstName,
dbo.Contacts.strSurname
FROM dbo.Property
INNER JOIN dbo.Tenancy ON dbo.Property.PropertyPK = dbo.Tenancy.PropertyFK
INNER JOIN dbo.Tenant ON dbo.Tenancy.TenancyPK = dbo.Tenant.TenancyFK
INNER JOIN dbo.Contacts ON dbo.Tenant.ContactFK = dbo.Contacts.ContactPK
The main table is the Property table and I filter out one row by specifying a PropertyPK in my criteria..
My question is.. If the Tenant or Contact record does not exist and I run my query in SQL Management Studio of course I get a message saying there are no rows but can I determine at what stage the join has failed between two tables?
I can of course check this in management studio but I am trying to help the user on the application side to inform them of why there are no rows. My application is in VB and I will write that check if there are no rows and I cannot determine it in SQL..
Sorry for the question in advance..
Derek.. :)
Simply use a LEFT JOIN:
SELECT p.PropertyPK, ty.TenancyPK, t.ContactFK,
c.strTitle, c.strFirstName, c.strSurname
FROM dbo.Property p LEFT JOIN
dbo.Tenancy ty
ON p.PropertyPK = ty.PropertyFK LEFT JOIN
dbo.Tenant t
ON ty.TenancyPK = t.TenancyFK LEFT JOIN
dbo.Contacts c
ON t.ContactFK = c.ContactPK;
This will keep all rows in the Property table. You can then see which primary keys are NULL to see if there were matches in the other tables.
Note that the query is much easier to write and to read when you use table aliases.

Joining Two Queries onto a Shared Table

I have been struggling with the concept of combining results of two queries together via a join on a common table and I was hoping I could gain some assistance. The following is a rough guide to the tables:
dbo.Asset (not returned in the SELECT statement, used for joins only)
- dbo.Asset.AssetID
- dbo.Asset.CatalogueID
dbo.WorkOrder
- WorkOrderID
- AssetID
- WorkOrderNumber
dbo.WorkOrderSpare
- WorkOrderID
- WorkOrderSpareID
- WorkOrderSpareDescription
- ActualQuantity
- CreatedDateTime
dbo.Catalogue
- CatalogueID (PK)
- CatalogueNumber
- CatalogueDescription
- CatalogueGroupID
dbo.CatalogueGroup
- CatalogueGroupID
- CatalogueGroupNumber
First Query:
SELECT CatalogueGroup.CatalogueGroupName,
Catalogue.CatalogueNumber,
Catalogue.CatalogueDescription,
Catalogue.CatalogueID,
Asset.IsActive
FROM CatalogueGroup
INNER JOIN Catalogue
ON CatalogueGroup.CatalogueGroupID = Catalogue.CatalogueGroupID
INNER JOIN Asset
ON Catalogue.CatalogueID = Asset.CatalogueID
Second Query:
SELECT WorkOrder.WorkOrderNumber,
WorkOrderSpare.WorkOrderSpareDescription,
WorkOrderSpare.ActualQuantity,
WorkOrderSpare.CreatedDateTime
FROM WorkOrder
INNER JOIN WorkOrderSpare
ON WorkOrder.WorkOrderID = WorkOrderSpare.WorkOrderID
Now I can do the above easily enough in Access (WYSIWYG) by joining Asset/Catalogue/CatalogueGroup together and then joining Asset.AssetID onto WorkOrder.AssetID. I can't seem to get anything similar to work via raw code, I think I have my logic correct for the joins (INNER JOIN on the results of both) but then I am new to this.
Any assistance would be greatly appreciated, any pointers on where I can read further into problems like this would be great.
EDIT: This is what I was trying to use to no avail, I should also mention I am trying to do this in ms-sql, not Access (trying to move away from drag and drop):
SELECT CatalogueGroup.CatalogueGroupName,
Catalogue.CatalogueNumber,
Catalogue.CatalogueDescription,
Catalogue.CatalogueID,
Asset.IsActive,
WorkOrderSpare.WorkOrderSpareDescription,
WorkOrderSpare.ActualQuantity,
WorkOrderSpare.CreatedDateTime,
WorkOrder.WorkOrderNumber
FROM (((CatalogueGroup
INNER JOIN Catalogue
ON CatalogueGroup.CatalogueGroupID = Catalogue.CatalogueGroupID)
INNER JOIN Asset ON Catalogue.CatalogueID = Asset.CatalogueID)
INNER JOIN WorkOrderSpare
ON WorkOrder.WorkOrderID = WorkOrderSpare.WorkOrderID)
INNER JOIN WorkOrder ON Asset.AssetID = WorkOrder.AssetID
Think I see the issue. Assuming that the joins themselves are correct (ie your columns do relate to each other), the order of your joins is a little off - when you join WorkOrder to WorkOrderSpare, neither of those two tables relate back to any table you've identified up until that point in the query. Think of it as joining two tables separately from the chain of joins you have going so far - it's almost like doing two separate join queries. If you switch the last two it should work, that way WorkOrder will join to Asset (which you've already defined) and then you can join WorkOrderSpare to WorkOrder. I've also taken the liberty of removing parentheses on the joins, that's an Access thing.
SELECT CatalogueGroup.CatalogueGroupName,
Catalogue.CatalogueNumber,
Catalogue.CatalogueDescription,
Catalogue.CatalogueID,
Asset.IsActive,
WorkOrderSpare.WorkOrderSpareDescription,
WorkOrderSpare.ActualQuantity,
WorkOrderSpare.CreatedDateTime,
WorkOrder.WorkOrderNumber
FROM CatalogueGroup
INNER JOIN Catalogue ON CatalogueGroup.CatalogueGroupID = Catalogue.CatalogueGroupID
INNER JOIN Asset ON Catalogue.CatalogueID = Asset.CatalogueID
INNER JOIN WorkOrder ON Asset.AssetID = WorkOrder.AssetID
INNER JOIN WorkOrderSpare ON WorkOrder.WorkOrderID = WorkOrderSpare.WorkOrderID
I think you were close. As a slightly different approach to joining, try this:
SELECT CatalogueGroup.CatalogueGroupName,
Catalogue.CatalogueNumber,
Catalogue.CatalogueDescription,
Catalogue.CatalogueID,
Asset.IsActive,
WorkOrderSpare.WorkOrderSpareDescription,
WorkOrderSpare.ActualQuantity,
WorkOrderSpare.CreatedDateTime,
WorkOrder.WorkOrderNumber
FROM
CatalogueGroup, Catalogue, Asset, WorkOrder, WorkOrderSpare
WHERE CatalogueGroup.CatalogueGroupID = Catalogue.CatalogueGroupID
and Catalogue.CatalogueID = Asset.CatalogueID
and Asset.AssetID = WorkOrder.AssetID
and WorkOrder.WorkOrderID = WorkOrderSpare.WorkOrderID
It looks like it should work, but not having data, hard to know if simple joins all the way through is what you want. (It's a matter of personal preference whether to use the and clauses rather than the inner join syntax. While on style preferences, I like table aliases if supported, so FROM CatalogueGroup cg for example, so that you can refer to cg.CatalogueGroupID etc, rather than writing out the full table name every time.)
Ok. so the error that you noted in a comment
The multi-part identifier "WorkOrder.WorkOrderID" could not be bound
is usually when you have an alias for a table and instead of using alias in JOIN you use the table name or when you are using the wrong column name or table name.
Ideally in SQL server your query should look like this
SELECT
cg.CatalogueGroupName,
c.CatalogueNumber,
c.CatalogueDescription,
c.CatalogueID,
A.IsActive,
Wo.WorkOrderNumber,
WoS.WorkOrderSpareDescription,
WoS.ActualQuantity,
WoS.CreatedDateTime
FROM CatalogueGroup cg
INNER JOIN Catalogue c ON cg.CatalogueGroupID = c.CatalogueGroupID
INNER JOIN Asset A ON c.CatalogueID = A.CatalogueID
INNER JOIN WorkOrder Wo ON Wo.AssetID= A.AssetID
INNER JOIN WorkOrderSpare WoS ON Wo.WorkOrderID = WoS.WorkOrderID

Basic SQL join question. Can you help me improve my skillset?

Ok.. So I'm trying to improve my SQL skills and have a question. Here is a screen shot of the schema.
Schema http://img509.imageshack.us/img509/97/screenhunter02nov121946.gif
(http://img509.imageshack.us/img509/97/screenhunter02nov121946.gif)
Alright so I'm selecting a bunch of Report Bundles and other rows from a table you can see. I've got these two tables joining together correctly and displaying what should be returned. Now I need to add another field onto my result rows that states what type of report this is. How can I join up to the ReportGroupType table through the ReportBundleGroup table without getting a shwack of results?
Here is the query I am using so far.
SELECT *
FROM ReportBundleCustomerVisibility INNER JOIN ReportBundle
ON ReportBundleCustomerVisibility.ReportBundleID = ReportBundle.ID
WHERE ReportBundleCustomerVisibility.ReferenceCustomerID = 2303
Thanks again SO
SELECT *
FROM ReportBundleCustomerVisibility AS v
JOIN ReportBundle AS b ON b.ID = v.ReportBundleID
JOIN ReportBundleGroup AS g ON b.ID = g.ReportBundleID
JOIN ReportGroupTYpe AS t ON t.ID = g.ReportGroupTypeID
WHERE v.ReferenceCustomerID = 2303
It sounds like you just need another inner join to get the information you need. You can think about the second join as joining the result of the join with the ReportGroupType table. I added parenthesis to try to join the two sets the second INNER JOIN is operating on.
SELECT * FROM ((ReportBundleCustomerVisibility
INNER JOIN ReportBundle ON ReportBundleCustomerVisibility.ReportBundleID = ReportBundle.ID)
INNER JOIN ReportGroupType ON ReportBundleGroup.ReportGroupTypeID = ReportGroupType.ID)
WHERE ReportBundleCustomerVisibility.ReferenceCustomerID = 2303
I also highly suggest against using "SELECT *" in production code or any query you plan on reusing as the table schema can change and possibly effect reports and UI. Explicitly specify the columns instead.