Right and Left Join Together in SQL - sql

I am trying to use a RIGHT and LEFT Join together. I have it working when only left joining one table. But I am trying to now include another table in my left join. It gives me an error saying I am missing an operator. Where am I missing a parenthesis?
FROM qSplit RIGHT JOIN (t_i360_agent AS i LEFT JOIN cmsAgent_Split AS c
ON ((i.LocalDay = c.LocalDay) AND (i.ACDID = c.LOGID))
LEFT JOIN qry_AllNewtables as qry ON (qry.custConvDate = c.LocalDay)
AND (qry.CustAgentLoginName = i.Loginname) ) ON qSplit.SPLIT = c.SPLIT

Don't use LEFT JOIN and RIGHT JOIN together. I imagine that somewhere there could be a query where it makes sense. In practice, I don't think I have ever used them both in the same query, possibly because I write queries using LEFT JOIN.
If you want everything in the agent table, then make it first! And use left join;
FROM t_i360_agent i LEFT JOIN
cmsAgent_Split c
ON i.LocalDay = c.LocalDay AND i.ACDID = c.LOGID LEFT JOIN
qry_AllNewtables qry
ON qry.custConvDate = c.LocalDay AND
qry.CustAgentLoginName = i.Loginname LEFT JOIN
qSplit
ON qSplit.SPLIT = c.SPLIT
It is much easier to follow the intention of the query this way. You are starting with the data that you think is so important that you want to keep all of it, even when JOINs have no matching rows.

Beside the suggestion by Gordon the problem was you miss a join condition for the RIGHT JOIN once I reformat the query was easy to see what was missing.
FROM qSplit
RIGHT JOIN t_i360_agent AS i
-- Need join condition
LEFT JOIN cmsAgent_Split AS c
ON (i.LocalDay = c.LocalDay)
AND (i.ACDID = c.LOGID))
LEFT JOIN qry_AllNewtables as qry
ON (qry.custConvDate = c.LocalDay)
AND (qry.CustAgentLoginName = i.Loginname)

Related

Odd Outer Joining Structure for a View

I am importing a view from an old database as part of a software upgrade and I saw this FROM clause as I was working.
FROM
t_store_master AS STM
RIGHT OUTER JOIN
dbo.t_shipping AS SHP
INNER JOIN
t_hu_master AS HUM
INNER JOIN
t_stored_item AS STO ON HUM.hu_id = STO.hu_id
ON SHP.shipment_id = HUM.reserved_for
AND SHP.location_id = HUM.location_id
INNER JOIN
dbo.t_carrier AS CAR ON SHP.carrier_code = CAR.carrier_code
LEFT OUTER JOIN
dbo.t_order_detail AS ORD
INNER JOIN
dbo.t_order AS ORM ON ORD.order_number = ORM.order_number
INNER JOIN
dbo.t_pick_detail PDL ON ORD.order_number = PDL.order_number
ON STO.type = PDL.pick_id
ON STM.store_id = HUM.control_number_2
It is my understanding that OUTER JOIN requires an ON clause in order to be interpreted properly by the compiler. However, there must be some edge case scenarios I am unaware of because the code above returns good data without throwing any errors.
After some goggling and reading up on MSDN standards for OUTER JOINs, I am still at a loss for what the LEFT OUTER JOIN and RIGHT OUTER JOIN are doing in this query.
I do know that the multiple ON clauses beneath the INNER JOINs are necessary. There seems to be some kind of hidden or implied mapping being done between the ON clauses and the OUTER JOINs. Past that I cannot tell what the purpose of writing a query this way would be.
Could someone shed some insight on how this works and why it would be written this way?
This is allowed. It makes slightly more sense with parentheses:
FROM t_store_master STM RIGHT OUTER JOIN
(dbo.t_shipping SHP INNER JOIN
(t_hu_master HUM INNER JOIN
t_stored_item STO
ON HUM.hu_id = STO.hu_id
)
ON SHP.shipment_id = HUM.reserved_for AND
SHP.location_id = HUM.location_id
) INNER JOIN
(dbo.t_carrier CAR
ON SHP.carrier_code = CAR.carrier_code LEFT OUTER JOIN
((dbo.t_order_detail ORD INNER JOIN
dbo.t_order ORM
ON ORD.order_number = ORM.order_number
) INNER JOIN
dbo.t_pick_detail PDL
ON ORD.order_number = PDL.order_number
)
ON STO.type = PDL.pick_id
)
ON STM.store_id = HUM.control_number_2
That said, I would recommend never writing a query like this and rewriting the query ASAP if it is in production code. At the very least, add the parentheses!
Parentheses are almost never needed in the FROM clause to express JOINs (there is one case where I do happen to use them). Non-interleaved ON clauses are never needed -- or at least, I have never had occasion to use them or think they were the best way to write a query. But, both are allowed.

Condition on main table in inner join vs in where clause

Is there any reason on an INNER JOIN to have a condition on the main table vs in the WHERE clause?
Example in INNER JOIN:
SELECT
(various columns here from each table)
FROM dbo.MainTable AS m
INNER JOIN dbo.JohnDataRecord AS jdr
ON m.ibID = jdr.ibID
AND m.MainID = #MainId -- question here
AND jdr.SentDate IS NULL
LEFT JOIN dbo.PTable AS p1
ON jdr.RecordID = p1.RecordID
LEFT JOIN dbo.DataRecipient AS dr
ON jdr.RecipientID = dr.RecipientID
(more left joins here)
WHERE
dr.lastRecordID IS NOT NULL;
Query with condition in WHERE clause:
SELECT
(various columns here from each table)
FROM dbo.MainTable AS m
INNER JOIN dbo.JohnDataRecord AS jdr
ON m.ibID = jdr.ibID
AND jdr.SentDate IS NULL
LEFT JOIN dbo.PTable AS p1
ON jdr.RecordID = p1.RecordID
LEFT JOIN dbo.DataRecipient AS dr
ON jdr.RecipientID = dr.RecipientID
(more left joins here)
WHERE
m.MainID = #MainId -- question here
AND dr.lastRecordID IS NOT NULL;
Difference in other similar questions that are more general whereas this is specific to SQL Server.
In the scope of the question,
Is there any reason on an INNER JOIN to have a condition on the main
table vs in the WHERE clause?
This is a STYLE choice for the INNER JOIN.
From a pure style reflection point of view:
While there is no hard and fast rule for STYLE, it is generally observed that this is a less often used style choice. For example that might generally lead to more challenging maintenance such as if someone where to remove the INNER JOIN and all the subsequent ON clause conditions, it would effect the primary table result set, OR make the query more difficult to debug/understand when it is a very complex set of joins.
It might also be noted that this line might be placed on many INNER JOINS further adding to the confusion.

Several ON clause in JOIN doesn't work properly in Access

The problem is really weird. The code below gives the error, that there is unsupportable JOIN statement
update ((s2t
left join tables on
S2T.[table] = Tables.TableName)
left join Columns on
(S2T.[column] = Columns.ColumnName))
left join s2t_source on
( s2t_source.source_table = "money")
set s2t.source_id = 1;
But then I changed join conditions on third JOIN this way and it started to work:
update ((s2t
left join tables on
S2T.[table] = Tables.TableName)
left join Columns on
(S2T.[column] = Columns.ColumnName))
inner join s2t_source on
( s2t_source.source_table = S2T.[table])
set s2t.source_id = 1;
What am I doing wrong? Firstly, I thought that problem related with ON clauses, that use info from just previously joined table. However then I found similar code, which seems to be work. I'm confused. How is that possible, that changing ON clause makes the query to fail?
upd1: I don't think that the problem related to datatype.
Text datatype: s2t_source.source_table, s2t_source.source_field, S2T.[table], S2T.[column], Tables.TableName, Columns.ColumnName
Integer datatype: Tables.id, Columns.id, s2t.source_id
upd2: I'm using Access 2010. Among this 3 tables, there are only 1 foreign key between tables named Tables and Columns
Tables.id = Columns.table_id
s2t_source.source_table = "money"
...is not a JOIN Condition but a WHERE Condition. The right hand site variable should contain something with the previous tables/joins.
Not knowing the context, I can only guess a solution:
update ((s2t
left join tables on
S2T.[table] = Tables.TableName)
left join Columns on
(S2T.[column] = Columns.ColumnName))
left join s2t_source on
( s2t_source.source_table = S2T.[table])
set s2t.source_id = 1
WHERE s2t_source.source_table = "money";

Join expression not supported SQL

SELECT
Trs.itemID, Trs.imtName, Trs.sumQty, Sum(whiQty)
FROM
((SELECT
trsitemID AS itemID, trsimtName AS imtName,
Sum(trsQty) As sumQty
FROM
tblTransactionSub AS T
WHERE
trstraID = 1231
AND trsActive = True
GROUP BY
trsitemID, trsimtName) AS Trs
INNER JOIN
tblWarehouseItem AS WHI ON Trs.itemID = WHI.whiitemID)
RIGHT JOIN
WHI ON Trs.trswhiID = WHI.whiID
WHERE
whiActive = True
AND whiCansel = False
AND whiwrhID = 19
GROUP BY
Trs.itemID,Trs.imtName, Trs.sumQty
HAVING
SUM(whiQty) < Trs.sumQty
If you please help me me out since I am new to SQL commands I can not easily find my mistake.
Thanks in advance
The error that occurred when I added the Right Join is:
Join expression not supported
In MS Access, you have to use parenthesises with multiple joins:
select ...
from
((table1
... join table2 on ...)
... join table3 on ...)
... join tableN
/edit/
As OP question changes its syntax often, then my answer seems out of place :) Initially there were no parens there.
About RIGHT JOIN: You need to use table name (or entire subselect) after JOIN keyword, not skip it or use some other alias. Your query part
RIGHT JOIN
WHI ON Trs.trswhiID = WHI.whiID
currently uses alias WHI, which is wrong in two ways: 1) it is not table name 2) it is already used. You need something like this:
RIGHT JOIN
tblWarehouseItem AS WHI2 ON Trs.trswhiID = WHI2.whiID
It could be possible that MS Access restricts your kind of JOINs usage (like INNER join should not come after LEFT join); I have currently no possibility to check precise rules.
Your problem is that you have no table name after the RIGHT JOIN:
RIGHT JOIN
ON Trs.trswhiID = WHI.whiID
Should be:
RIGHT JOIN YOURTABLENAMEHERE as alias
ON Trs.trswhiID = WHI.whiID
However, you have already defined Trs and Whi, so I have no idea what table you want there, or why. Perhaps you just want to change the INNER JOIN to a LEFT JOIN or RIGHT JOIN.

Refactor SQL (workaround RIGHT OUTER JOIN)

Since SQLite does not support RIGHT OUTER JOINS I pose the following challenge (read: invitation to do my work for me):
Refactor this query so it no longer utilises SQLite-unsupported constructs like RIGHT/FULL OUTER JOINs.
SELECT strings.*, translations.text
FROM translations INNER JOIN
language ON translations.language_id = language.id RIGHT OUTER JOIN
strings ON translations.string_id = strings.id
WHERE (language.handle = 'english')
I sense it can be achieved with subqueries or by pivoting the tables and performing a LEFT OUTER JOIN but my attempts have failed; my SQL's not what it used to be.
Here's a query builder outline showing the applicable schema: http://dl.getdropbox.com/u/264612/sql-refactor.PNG
First to crack it gets an e-hug from dekz
The following is untested.
select strings.*, translations.text
from strings left outer join translations
on translations.string_id = strings.id
and translations.language_id = (select id
from language
where language.handle = 'english')
I think this will give you all strings with the matching translation text where a suitable translation exists in English. Is that what you are trying to get?
Intriguing that SQLite allows LEFT OUTER JOINs but not RIGHT OUTER JOINs. Well, since it does allow LEFT OUTER JOINs, you're right, you can just rearrange the join order:
SELECT strings.*, translations.text
FROM strings LEFT OUTER JOIN (
translations INNER JOIN language ON translations.language_id = language.id
) tr ON tr.string_id = strings.id
WHERE (language.handle = 'english')
[EDIT: Applied Blorgbeard's suggestion of naming the joined table to get the query to parse -- hope it works now!]