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

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.

Related

How do I find matching data from two tables?

Sorry for the lack of experience in advance.
I have cleansed my diagnostics table and want extract just the rows from followup questions that share the same string in both the AssetType and RepairType columns as the diagnostics table.
Is there a statement or join I can do that will bring back those results?
What you can do is perform an inner join from diagnostics to followupquestions:
SELECT * FROM
Diagnostics D
INNER JOIN
FollowupQuestions F
ON
D.AssetType = F.AssetType
AND
D.RepairType = F.RepairType
An inner join will only return rows where the ON condition is met.

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

Can I do a left join without returning the conditional columns?

New to SQL but I want to be able to optimize my query by bringing just the right amount of data. I am doing a left join on CS Rep Name and WE, which are two columns present in both tables. I find that if I don't bring in CS Rep Name and WE in the TECDR table, the query would error. Is there a workaround to this? Since it is a left join, I don't need redundant data.
SELECT *
FROM Tish_Email_CSAT_Dump AS TECD
LEFT JOIN (SELECT CS_Rep_Name,
Team_Leader,
Operations_Manager,
Tenure,
WE,
FileName
FROM Tish_Email_CSAT_Dump_Roster) AS TECDR
ON TECD.CS_Rep_Name = TECDR.CS_Rep_Name
AND TECD.WE = TECDR.WE
When you embed a SELECT inside a query in place of a table, the result of a select (projection) behave like a table visible only inside the query.
In your case, the join is the same as if there were a table called TECDR with the columns that you select. Hence, if you leave out some columns of Tish_Email_CSAT_Dump_Roster from your SELECT, these columns would not be available for joining or selection.
However, in your case this is unnecessary: all you need to do is joining to the underlying table, like this:
SELECT
TECD.*
, TECDR.Team_Leader
, TECDR.Operations_Manager
, TECDR.Tenure
, TECDR.FileName
FROM Tish_Email_CSAT_Dump AS TECD
LEFT JOIN Tish_Email_CSAT_Dump_Roster AS TECDR
ON TECD.CS_Rep_Name = TECDR.CS_Rep_Name AND TECD.WE = TECDR.WE
select
<place the columns you want here>
from
Tish_Email_CSAT_Dump as TECD
Left join Tish_Email_CSAT_Dump_Roster as TECDR
On TECD.CS_Rep_Name = TECDR.CS_Rep_Name and TECD.WE = TECDR.WE
Hope the following helps or else please share the query that errors:
select TECD.Column1, TECD.Column2, TECDR.Column1, TECDR.Column2
from Tish_Email_CSAT_Dump as TECD
Left join Tish_Email_CSAT_Dump_Roster as TECDR
On TECD.CS_Rep_Name = TECDR.CS_Rep_Name and TECD.WE = TECDR.WE

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