Error when left joining two databases (SQL Server) - sql

I have a great problem with joining two MSSQL databases together (on the same server) using LEFT JOIN. I run this SQL from the database OLAB_DB and get the error:
The multi-part identifier "OLAP_DB.dbo.OLAP_invoice.UserID" could not be bound.
There seem to be a problem with the DB not being able to find itself, and I have no idea of how to solve this. I have double and triple checked the spelling and rewrote the SQL several times, but now I just have to give up and ask for help :(
This doesn't work:
SELECT TOP 200
COALESCE(LTRIM(RTRIM(contact_db.dbo.ContactTable.EmailAdr)),LTRIM(RTRIM(contact_db.dbo.CustomerTable.EmailAdr))) AS EMAIL,
OLAP_invoice.OrdreLinjeID AS ORDERNO
OLAP_invoice.SalgsPris AS PRICE,
OLAP_invoice.UserID AS CONTACTID
FROM OLAP_invoice,contact_db.dbo.CustomerTable
LEFT JOIN contact_db.dbo.ContactTable
ON OLAP_DB.dbo.OLAP_invoice.UserID = contact_db.dbo.ContactTable.UserID
WHERE contact_db.dbo.CustomerTable.ClientID = OLAP_invoice.ClientID
But skipping the left join and just getting data from the two different databases works just fine.
This works just fine:
SELECT TOP 200
LTRIM(RTRIM(contact_db.dbo.CustomerTable.EmailAdr)) AS EMAIL,
LTRIM(RTRIM(contact_db.dbo.ContactTable.UserID)) AS EMAIL2,
OLAP_invoice.OrdreLinjeID AS ORDERNO
OLAP_invoice.SalgsPris AS PRICE,
OLAP_invoice.UserID AS CONTACTID
FROM OLAP_invoice,contact_db.dbo.CustomerTable
WHERE contact_db.dbo.CustomerTable.ClientID = OLAP_invoice.ClientID
AND contact_db.dbo.ContactTable.UserID = OLAP_invoice.UserID
The reason I need the LEFT JOIN, is because some orders are not registered with a UserID (only ClientID).
I have checked the access rights and there is no problem to access the fields individually, the problem occurs when I have to compare the values in the LEFT JOIN and specifies the absolute path.
Do you have any idea of what can be wrong?

You can try this:
SELECT TOP 200 COALESCE(LTRIM(RTRIM(contact_db.dbo.ContactTable.EmailAdr)),LTRIM(RTRIM(contact_db.dbo.CustomerTable.EmailAdr))) AS EMAIL,
OLAP_invoice.OrdreLinjeID AS ORDERNO
OLAP_invoice.SalgsPris AS PRICE,
OLAP_invoice.UserID AS CONTACTID
FROM OLAP_invoice LEFT JOIN contact_db.dbo.ContactTable ON OLAP_DB.dbo.OLAP_invoice.UserID = contact_db.dbo.ContactTable.UserID, contact_db.dbo.CustomerTable
WHERE contact_db.dbo.CustomerTable.ClientID = OLAP_invoice.ClientID

You are selecting from OLAP_invoice, but joining to OLAP_DB.dbo.OLAP_invoice. You need to qualify the table exactly the same every time, or use an alias.
So either:
FROM OLAP_DB.dbo.OLAP_invoice
left join contact_db.dbo.ContactTable
on OLAP_DB.dbo.OLAP_invoice...
OR
FROM ROM OLAP_invoice
LEFT JOIN ontact_db.dbo.ContactTable
ON OLAP_invoice...
Or you could use an alias as well, less typing that way.
FROM OLAP_invoice OI
LEFT JOIN ontact_db.dbo.ContactTable CT
ON OI...

Personally, I try to avoid having multiple tables in my FROM without intentionally specifying the type of join.
I find something like this to be much more readable and maintainable :
SELECT TOP 200
COALESCE( LTRIM(RTRIM(con.EmailAdr)), LTRIM(RTRIM(cus.EmailAdr)) ) AS EMAIL,
i.OrdreLinjeID AS ORDERNO
i.SalgsPris AS PRICE,
i.UserID AS CONTACTID
FROM OLAP_invoice i
LEFT JOIN contact_db.dbo.CustomerTable cus ON cus.ClientID = i.ClientID
LEFT JOIN contact_db.dbo.ContactTable con ON con.UserID = i.UserID

Related

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

MS Access - SQL nested inner join

Just need to ask for your help, I have been having some problems with MS Access, I'm trying to create a nested INNER JOIN to perform a query. All of the fields that I need are showing up, however when I try to add a new entry it gives me an error
Can't Add Records Join key of table is not in record set.
Here's my code:
SELECT
Applicant_ID, Complete_Name, Date_of_Birth, Date_of_Application, Gender,
City_Address, Position_Applied, Civil_Status, Age, Educational_Attainment,
Table_JuniorRecruiter.Junior_Recruiter_ID, Junior_Recruiter_Name, Exam_Remarks,
Table_Exam.Exam_Number
FROM
(Table_Applicant
INNER JOIN
Table_Exam ON Table_Applicant.Exam_Number = Table_Exam.Exam_Number)
INNER JOIN
Table_JuniorRecruiter ON Table_Applicant.Junior_Recruiter_ID = Table_JuniorRecruiter.Junior_Recruiter_ID;
The brackets you have round the first table and its first inner join give a syntax error. Between the ( and the ) needs to be a complete SELECT statement, and you start off with a table name, which no valid SELECT statement will do.
Now I don't actually know what you're trying to do, but this will be valid SQL:
SELECT
Applicant_ID, Complete_Name, Date_of_Birth, Date_of_Application, Gender,
City_Address, Position_Applied, Civil_Status, Age, Educational_Attainment,
Table_JuniorRecruiter.Junior_Recruiter_ID, Junior_Recruiter_Name, Exam_Remarks,
Table_Exam.Exam_Number
FROM
Table_Applicant
INNER JOIN
Table_Exam ON Table_Applicant.Exam_Number = Table_Exam.Exam_Number
INNER JOIN Table_JuniorRecruiter
ON Table_Applicant.Junior_Recruiter_ID
= Table_JuniorRecruiter.Junior_Recruiter_ID
Here I've just taken out the ( and the ). It should be valid SQL (provided the table and column names are correct) but it might not be the actual query you want.
However, I can't see what you'd gain by making the table_applicant and table_exam join a nested subquery: doing that looks totally un-necessary.

Join with select SQL query?

I'm trying to run a query on a table (the one Wordpress uses) where I want to select the ID and post_type columns from one table, then do a Left Join to another table, two separate times (getting separate data).
This is what I have so far, but it's not cutting the mustard:
SELECT derby_posts.id AS pID,
derby_posts.post_type AS tier
FROM derby_posts
LEFT JOIN (SELECT derby_postmeta.post_id AS dbID1,
derby_postmeta.meta_key AS dbMeta1)
ON pid = dbid1
AND dbmeta1 = 'twitter'
LEFT JOIN (SELECT derby_postmeta.post_id AS dbID2,
derby_postmeta.meta_key AS dbMeta2)
ON pid = dbid2
AND dbmeta2 = 'website'
WHERE tier IN ('local', 'regional', 'national')
I'm sure I'm missing something super simple...
Edit: here's the solution that worked for me. Table alias helped, putting all my SELECT statements together cleaned things up. Also, I realized I could remove items from the SELECT, even though I'm using them in the Join, which cleans up the results a lot.
SELECT
db.ID as id,
db.post_type as tier,
dpm1.meta_value as twitter,
dpm2.meta_value as website
FROM derby_posts db
LEFT JOIN derby_postmeta dpm1 ON (db.ID = dpm1.post_id AND dpm1.meta_key = 'twitter' )
LEFT JOIN derby_postmeta dpm2 ON (db.ID = dpm2.post_id AND dpm2.meta_key = 'website' )
WHERE db.post_type IN ('local','regional','national')
I 'm sure I'm missing something super simple...
You are right!
You need to give your selects an alias, and use that alias in the ON clause. You are also missing a FROM <table> - a required part of a SELECT statement that reads from a table:
LEFT JOIN (
SELECT derby_postmeta.post_id AS dbID1,
derby_postmeta.meta_key AS dbMeta1
FROM someTable
) dpm ON pid = dpm.dbid1 AND dpm.dbmeta1 = 'twitter'
I gave the results of your SELECT an alias dpm, and used it to "link up" the rows from the inner select to the rows of your outer select.
SELECT
db.derby_posts.ID as pID,
db.derby_posts.post_type as tier,
dpm1.post_id as dbID1,
dpm1.meta_key as dbMeta1,
dpm2.post_id as dbID2,
dpm2.meta_key as dbMeta2
FROM derby_posts db
LEFT JOIN derby_postmeta dpm1 ON (db.pID = dpm1.post_id AND dpm1.meta_key= 'twitter')
LEFT JOIN derby_postmeta dpm2 ON (db.pID = dbm2.post_id AND dbm2.meta_key = 'website')
WHERE tier IN ('local','regional','national')

Unknown column on 'on clause' in sql joins?

Can you guys help me please in understanding the SQL specifications on join. I don't understand it. I kept getting errors called Unknown column list on on clause.
I got this error over my SQL syntax, I almost rubbed it in my face I just can't understand why it is not working, I have read some article regarding that it is because of precedence etc but I am really confused on what I have done wrong here.
select product.name , product.price from product inner join product_category on
(product_category.product_no = product.product_no ) where product_category.sub_category =
"COFFIN";
I know this question have been ask a hudred and million times here, but the ones I saw are complicated nowhere close in this very basic sql syntax.
THanks for helping me out.
EDIT:
I just had realize that I have product_category not a direct child to my product table so
I just have typed
select * from product
join specifications
join product_category on ( specifications.product_no = product_category.product_no);
But this still gave me an error, unknown column product_category.
I've read and followed some instruction similarly to this sites:
MYSQL unknown clause join column in next join
Unknown column {0} in on clause
MySQL "Unknown Column in On Clause"
I am really frustrated. I really can't get it to work.
For each new table you join in your query, each table must have at least one ON clause. It's hard to know exactly what you're trying to do without knowing the schema (table names, columns, etc), but here's an example
select *
from product p
join specifications s
on p.product_no = s.product_no
join product_category pc
on pc.spec_no = p.spec_no
Check out this link on table aliases as well. Gives a good example on joins + really useful info on how to increase the readability of your SQL
http://msdn.microsoft.com/en-us/library/ms187455(v=sql.90).aspx
I found this article useful as well as it visually displays the different types of joins
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
You are missing the part where you specify the joining conditions between product and specifcations.
select * from product
join specifications YOU NEED SOMETHING HERE
join product_category on etc
I modified the SQL syntax to look like this, I have overlook a key that connects product_category onto specification so I made necessary link and it worked!!!
SELECT *
FROM product
JOIN specifications ON ( product.product_no = specifications.product_no )
JOIN product_category ON ( specifications.spec_no = product_category.spec_no )
WHERE product_category.sub_category = "COFFIN"
LIMIT 0 , 30
Also thanks for the heads up on missing joining condition on specifications. Heck this carelessness cost so much time.
Thank you so much!
The default join type is an inner join. So if you write join, the database reads inner join, and insist that you include an on clause.
If you'd like to join without a condition, specify the cross join explicitly:
select *
from product p
cross join
specifications s
inner join
product_category pc
on pc.product_no = p.product_no
left join
some_other_table sot
on 1=1
The last join, with the on 1=1 condition, is another way to do a cross join. It's subtly different in that it will return rows from the left table even if the right table is empty.
Example at SQL Fiddle.

How do I remove a nested select from this SQL statement

I have the following SQL:
SELECT * FROM Name
INNER JOIN ( SELECT 2 AS item, NameInAddress.NameID as itemID, NameInAddress.AddressID
FROM NameInAddress
INNER JOIN Address ON Address.AddressID = NameInAddress.AddressID
WHERE (Address.Country != 'UK')
) AS Items ON (Items.itemID = Name .Name ID)
I have been asked to remove the nested select and use INNER JOINS instead, as it will improve performance, but I'm struggling.
Using SQL Server 2008
Can anyone help?
Thanks!
Your query is not correct as you're using Items.itemID while it's not in the subselect
I guess this is what you meant:
SELECT Name.*
FROM Name
INNER JOIN NameInAddress
ON Name.NameID = NameInAddress.NameID
INNER JOIN Address
ON Address.AddressID = NameInAddress.AddressID
WHERE (Address.Country != 'UK')
EDIT: The exact translation of your query would start with a SELECT Name.*, 2 as Item, NameInAddress.NameID, NameInAddress.AddressID though
It is one of those long-lived myths that nested selects are slower than joins. It depends completely on what the nested select says. SQL is just a declarative language to tell what you want done, the database will transform it into completely different things. Both MSSQL and Oracle (and I suspect other major engines as well) are perfectly able to transform correlated subqueries and nested views into joins if it is beneficial (unless you do really complex things which would be very hard, if possible, to describe with normal joins.
SELECT 2 AS Item, *
FROM Name
INNER JOIN NameInAddress
ON Name.NameID = NameInAddress.NameID
INNER JOIN Address
ON Address.AddressID = NameInAddress.AddressID
WHERE Address.Country != 'UK'
PS: Don't use "*". This will increase performance too. :)