Can you have an INNER JOIN without the ON keyword? - sql

While debugging into some Oracle code, I came across this query:
SELECT TPM_TASK.TASKID FROM TPM_GROUP
INNER JOIN TPM_USERGROUPS ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID
INNER JOIN TPM_TASK
INNER JOIN TPM_GROUPTASKS ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID
INNER JOIN TPM_PROJECTVERSION ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID
INNER JOIN TPM_TASKSTAGE ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID
INNER JOIN TPM_PROJECTSTAGE ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID
ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
I'm confused by the line:
INNER JOIN TPM_TASK
I haven't seen a JOIN without an ON clause before. Also confusing is the line:
ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
This seems like a random ON clause without any matching JOIN. The query runs without any errors, and returns a bunch of data, so obvious the syntax is perfectly valid. Can someone shed some light on exactly what's going on here?

Small universe... I ran across a tool generating this syntax yesterday and was rather flummoxed.
Apparently,
FROM a
INNER JOIN b
INNER JOIN c ON (b.id = c.id)
ON (a.id = c.id)
is equivalent to a nested subquery
FROM a
INNER JOIN (SELECT <<list of columns>>
FROM b
INNER JOIN c ON (b.id=c.id)) c
ON (a.id = c.id)

I think that this is only a problem of ordering your query (since there are only INNER JOINs, the order of them is not really that important). I rearrenged your query and now it looks like this:
SELECT TPM_TASK.TASKID
FROM TPM_GROUP
INNER JOIN TPM_USERGROUPS
ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID
INNER JOIN TPM_GROUPTASKS
ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
INNER JOIN TPM_TASK
ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID
INNER JOIN TPM_PROJECTVERSION
ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID
AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID
INNER JOIN TPM_TASKSTAGE
ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID
INNER JOIN TPM_PROJECTSTAGE
ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID
Does it make more sense to you now?, it does to me.

It'd look fine if it had parenthesis in there...
SELECT TPM_TASK.TASKID
FROM
TPM_GROUP
INNER JOIN TPM_USERGROUPS ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID
INNER JOIN (
TPM_TASK
INNER JOIN TPM_GROUPTASKS ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID
INNER JOIN TPM_PROJECTVERSION ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID
AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID
INNER JOIN TPM_TASKSTAGE ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID
INNER JOIN TPM_PROJECTSTAGE ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID
) ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
but since they are all inner joins I agree with Lamak's answer.

Related

SQL inner join multi part identifier could not be bound

I have a stored procedure with a bunch of joins I can not figure out why this is not working - I get an error:
The multi-part identifier "[table.column]" could not be bound.
This is an altered bit of SQL the original is -
dbo.Release
INNER JOIN
dbo.Cartridge
INNER JOIN
dbo.PriceClass AS PriceClass ON dbo.Cartridge.PriceClassId = PriceClass.Id
INNER JOIN
dbo.CartridgeType ON dbo.Cartridge.CartridgeTypeId = dbo.CartridgeType.Id
ON dbo.Release.Id = dbo.Cartridge.ReleaseId
INNER JOIN
dbo.OemSegmentation
INNER JOIN
dbo.OemProduct ON dbo.OemSegmentation.OemProductId = dbo.OemProduct.Id
INNER JOIN
dbo.OemPlatform ON dbo.OemSegmentation.OemPlatformId = dbo.OemPlatform.Id
INNER JOIN
dbo.OemMediaType ON dbo.OemSegmentation.OemMediaTypeId = dbo.OemMediaType.Id
ON dbo.CartridgeType.Id = dbo.OemSegmentation.SupplCartTypeId
OR dbo.CartridgeType.Id = dbo.OemSegmentation.CartridgeTypeId
LEFT OUTER JOIN
dbo.CartridgeCoverage ON dbo.Cartridge.Id = dbo.CartridgeCoverage.CartridgeId
What I am trying to change it to -
dbo.Release
INNER JOIN
dbo.Cartridge
INNER JOIN
dbo.PriceClass AS PriceClass ON dbo.Cartridge.PriceClassId = PriceClass.Id
INNER JOIN
dbo.CartridgeType ON dbo.Cartridge.CartridgeTypeId = dbo.CartridgeType.Id
ON dbo.Release.Id = dbo.Cartridge.ReleaseId
INNER JOIN
dbo.OemProduct ON OemSegmentation.OemProductId = dbo.OemProduct.Id
INNER JOIN
dbo.OemPlatform ON dbo.OemSegmentation.OemPlatformId = dbo.OemPlatform.Id
INNER JOIN
dbo.OemMediaType ON dbo.OemSegmentation.OemMediaTypeId = dbo.OemMediaType.Id
LEFT OUTER JOIN
dbo.CartridgeCoverage ON dbo.Cartridge.Id = dbo.CartridgeCoverage.CartridgeId
The error happens on these lines
INNER JOIN
dbo.OemProduct ON OemSegmentation.OemProductId = dbo.OemProduct.Id
INNER JOIN
dbo.OemPlatform ON dbo.OemSegmentation.OemPlatformId = dbo.OemPlatform.Id
INNER JOIN
dbo.OemMediaType ON dbo.OemSegmentation.OemMediaTypeId = dbo.OemMediaType.Id
Once you have aliased your table, use the alias to use TWO PART names for columns. i.e [TableAlias].[ColumnName]
I belive you have use column namd Id in all your tables commonly, so whenever you are picking Id column just go for [TableName].Id.
It seems you missed join: "INNER JOIN dbo.OemSegmentation"

How can I avoid using the NOT IN and the SUBSELECT in the following query

How can I avoid using the NOT IN subselect in this query and also avoid the subselect ?
select idTipoDocumento,idDocumentoTarea
from ArchivosTarea as a
inner join Tarea as b on a.idEstadoTarea=b.idTarea
where b.idTarea = 160
and idDocumentoTarea not in (select idDocumentoTarea
from ArchivosTarea as a
inner join tiposArchivos as b on a.idTipoDocumento = b.idTipoArchivo
inner join documentoSolicitud as c on b.idTipoArchivo = c.Id_tipo_archivo
inner join tarea as d on a.idEstadoTarea=d.idTarea
where d.idTarea = 160)
I know that probably a LEFT JOIN or something like that should do the trick but I have tried that and it does not provide me the same results as this query.
The actual idea is to avoid the SUBSELECT (of the WHERE) and also avoid the NOT IN.
Using left join:
Select A.idTipoDocumento,A.idDocumentoTarea from
(select idTipoDocumento,idDocumentoTarea
from ArchivosTarea as a
inner join Tarea as b on a.idEstadoTarea=b.idTarea
where b.idTarea = 160)A
left outer join
(select idDocumentoTarea from ArchivosTarea as a
inner join tiposArchivos as b on a.idTipoDocumento = b.idTipoArchivo
inner join documentoSolicitud as c on b.idTipoArchivo = c.Id_tipo_archivo
inner join tarea as d on a.idEstadoTarea=d.idTarea
where d.idTarea = 160)B
on A.idDocumentoTarea=B.idDocumentoTarea
where B.idDocumentoTarea is null
It happens that SQL Server has antijoin aka semiminus aka EXCEPTION JOIN. It return rows in the left argument that don't match when joined by the right.
select idTipoDocumento,idDocumentoTarea
from ArchivosTarea as a
inner join Tarea as b on a.idEstadoTarea=b.idTarea
and b.idTarea = 160
exception join (
select idDocumentoTarea
from ArchivosTarea as a
inner join tiposArchivos as b on a.idTipoDocumento = b.idTipoArchivo
inner join documentoSolicitud as c on b.idTipoArchivo = c.Id_tipo_archivo
inner join tarea as d on a.idEstadoTarea=d.idTarea
where d.idTarea = 160)
You can do this with LEFT JOIN. Also using NOT EXISTS.

LEFT JOINS in MS Access

I am trying to troubleshoot someone else's MS Access query and keep getting an invalid operation error. The Help doesn't seem to apply as I am just running a query. It all works as INNER JOINS but when I switch back to the LEFT JOIN the error.
SELECT *
FROM ((((orders
INNER JOIN orders_customers ON orders.CUST_ORDER_ID = orders_customers.ID)
LEFT JOIN quoted_theory ON orders.PART_ID = quoted_theory.PART_ID)
LEFT JOIN conversions ON orders.PART_ID = conversions.PART_ID)
LEFT JOIN dbo_WO_Header ON orders.CUST_ORDER_ID = dbo_WO_Header.PPC_Number)
INNER JOIN lines_qry ON orders.CUST_ORDER_ID = lines_qry.WORKORDER_BASE_ID
I can get one level of LEFT JOIN, but each time I add a second LEFT JOIN the error pops up.
Access' db engine frequently balks when mixing INNER and LEFT joins. If that query works without the last inner join ...
SELECT *
FROM
(((orders INNER JOIN orders_customers
ON orders.CUST_ORDER_ID = orders_customers.ID)
LEFT JOIN quoted_theory
ON orders.PART_ID = quoted_theory.PART_ID)
LEFT JOIN conversions
ON orders.PART_ID = conversions.PART_ID)
LEFT JOIN dbo_WO_Header
ON orders.CUST_ORDER_ID = dbo_WO_Header.PPC_Number
... then you could try that part as a subquery and inner join lines_qry to the subquery. It might get past the error.
SELECT *
FROM
(
SELECT *
FROM
(((orders INNER JOIN orders_customers
ON orders.CUST_ORDER_ID = orders_customers.ID)
LEFT JOIN quoted_theory
ON orders.PART_ID = quoted_theory.PART_ID)
LEFT JOIN conversions
ON orders.PART_ID = conversions.PART_ID)
LEFT JOIN dbo_WO_Header
ON orders.CUST_ORDER_ID = dbo_WO_Header.PPC_Number
) AS sub
INNER JOIN lines_qry
ON sub.CUST_ORDER_ID = lines_qry.WORKORDER_BASE_ID
If any other table besides orders includes a field named CUST_ORDER_ID, you will need something other than SELECT * within the subquery to avoid ambiguity.
SELECT *
FROM
(
SELECT *
FROM
(((orders INNER JOIN orders_customers
ON orders.CUST_ORDER_ID = orders_customers.ID)
LEFT JOIN quoted_theory
ON orders.PART_ID = quoted_theory.PART_ID)
LEFT JOIN conversions
ON orders.PART_ID = conversions.PART_ID)
LEFT JOIN dbo_WO_Header
ON orders.CUST_ORDER_ID = dbo_WO_Header.PPC_Number
) AS sub
INNER JOIN lines_qry
ON sub.CUST_ORDER_ID = lines_qry.WORKORDER_BASE_ID

SQL Syntax error in FROM clause

Here is the code I'm running into an error with:
FROM
IndexPID
INNER JOIN Demographics ON
IndexPID.NDoc_Number = Demographics.NDoc_Number,
PatientSupply
INNER JOIN Demographics ON
PatientSupply.NDocNum = Demographics.NDoc_Number
I also tried it this way:
FROM
IndexPID, PatientSupply
INNER JOIN Demographics ON
IndexPID.NDoc_Number = Demographics.NDoc_Number
INNER JOIN Demographics ON
PatientSupply.NDocNum = Demographics.NDoc_Number
But no cigar. Anybody tell me what I'm doing wrong?
You were very close:
FROM IndexPID
INNER JOIN Demographics
ON IndexPID.NDoc_Number = Demographics.NDoc_Number
INNER JOIN PatientSupply
ON Demographics.NDoc_Number = PatientSupply.NDocNum
would be easier if you posted the whole SQL!
Try
FROM
IndexPID
INNER JOIN Demographics ON
IndexPID.NDoc_Number = Demographics.NDoc_Number
INNER JOIN PatientSupply ON
PatientSupply.NDocNum = Demographics.NDoc_Number
You are mixing implicit (comma-separated) and explicit JOINs in an odd way here. It should look like the following, using explicit INNER JOINs only, with no commas between table names or ON clauses:
FROM
IndexPID
INNER JOIN Demographics
ON IndexPID.Ndoc_Number = Demographics.NDoc_Number
INNER JOIN PatientSupply
ON PatientSupply.NDocNum = Demographics.NDoc_Number
You uses inner join so you can use:
FROM Demographics
inner join IndexPID on Demographics.NDoc_Number=IndexPID.NDoc_Number
inner join PatientSupply on Demographics.NDoc_Number=PatientSupply.NDocNum

Sql problem with my query

SELECT
dbo.pi_employee.emp_firstname, dbo.pi_employee.emp_lastname,
dbo.pi_employee.emp_no, dbo.pi_employee.emp_cnic,
dbo.pi_employee.emp_currentadd, dbo.pi_employee.emp_cellph,
dbo.pi_employee.emp_birthday, pi_jobtitle_1.jobtitle_name,
dbo.pi_employee.emp_joindate, dbo.pi_education.edu_degree,
dbo.pi_education.edu_year, dbo.pi_employee.emp_pension,
dbo.pi_employee.emp_age, dbo.pi_employee.emp_service,
dbo.pi_employee.emp_terminate, dbo.pi_employee.emp_termdate,
dbo.pi_employee.emp_basicofpay, dbo.pi_employee.emp_terminationreason,
dbo.pi_employee.emp_terminationdate, dbo.pi_employee.emp_status,
dbo.pi_employee.emp_gender, dbo.pi_employee.emp_maritalstatus,
dbo.pi_employee.emp_paymethod, dbo.pi_employee.emp_leaveentitle,
dbo.pi_employee.emp_confirmation, dbo.pi_employee.emp_title,
dbo.pi_employee.emp_basicamount, dbo.pi_salgrade.salgrade_name,
dbo.tbl_emp_status.StatusName, dbo.pi_skills.skill_type,
dbo.pi_location.loc_name, pi_location_1.loc_name AS wcity,
dbo.pi_jobtitlehist.jthSaleGradetype, dbo.pi_workexp.exp_serperiod,
dbo.pi_employee.emp_domicile, dbo.pi_skills.skill_type AS Skill,
dbo.pi_skills.skill_exp, dbo.pi_education.edu_degree AS Degree,
dbo.pi_education.edu_uni, dbo.pi_education.edu_distinction,
dbo.pi_lochistory.lhstart_date, dbo.pi_lochistory.lhend_date
FROM
dbo.pi_location
RIGHT OUTER JOIN
dbo.pi_workexp
RIGHT OUTER JOIN
dbo.pi_employee ON dbo.pi_workexp.emp_no = dbo.pi_employee.emp_no
LEFT OUTER JOIN
dbo.pi_jobtitlehist ON dbo.pi_employee.emp_no = dbo.pi_jobtitlehist.emp_no ON
dbo.pi_location.loc_id = dbo.pi_employee.emp_location_id
LEFT OUTER JOIN
dbo.pi_salgrade ON dbo.pi_employee.emp_salgrade_id = dbo.pi_salgrade.salgrade_id
LEFT OUTER JOIN
dbo.tbl_emp_status ON dbo.pi_employee.emp_status = dbo.tbl_emp_status.StatusID
LEFT OUTER JOIN
dbo.pi_skills ON dbo.pi_employee.emp_no = dbo.pi_skills.emp_no
LEFT OUTER JOIN
dbo.pi_location AS pi_location_1
INNER JOIN
dbo.pi_lochistory ON pi_location_1.loc_id = dbo.pi_lochistory.loc_id ON dbo.pi_employee.emp_no = dbo.pi_lochistory.emp_no
LEFT OUTER JOIN
dbo.pi_education ON dbo.pi_employee.emp_no = dbo.pi_education.emp_no
LEFT OUTER JOIN
dbo.pi_jobtitle AS pi_jobtitle_1 ON dbo.pi_employee.emp_jobtitle_id = pi_jobtitle_1.jobtitle_id
I am writing sql query to implement different scenario, but problem is that it gives repeated values. I write distinct and order by too but result was same can any one help me to solve this issue.
EDIT – The same query with table names aliased:
SELECT
em.emp_firstname, em.emp_lastname,
em.emp_no, em.emp_cnic,
em.emp_currentadd, em.emp_cellph,
em.emp_birthday, jt.jobtitle_name,
em.emp_joindate, ed.edu_degree,
ed.edu_year, em.emp_pension,
em.emp_age, em.emp_service,
em.emp_terminate, em.emp_termdate,
em.emp_basicofpay, em.emp_terminationreason,
em.emp_terminationdate, em.emp_status,
em.emp_gender, em.emp_maritalstatus,
em.emp_paymethod, em.emp_leaveentitle,
em.emp_confirmation, em.emp_title,
em.emp_basicamount, sg.salgrade_name,
es.StatusName, s.skill_type,
L.loc_name, L1.loc_name AS wcity,
jh.jthSaleGradetype, we.exp_serperiod,
em.emp_domicile, s.skill_type AS Skill,
s.skill_exp, ed.edu_degree AS Degree,
ed.edu_uni, ed.edu_distinction,
Lh.lhstart_date, Lh.lhend_date
FROM
dbo.pi_location AS L
RIGHT OUTER JOIN
dbo.pi_workexp AS we
RIGHT OUTER JOIN
dbo.pi_employee AS em ON we.emp_no = em.emp_no
LEFT OUTER JOIN
dbo.pi_jobtitlehist jh ON em.emp_no = jh.emp_no ON L.loc_id = em.emp_location_id
LEFT OUTER JOIN
dbo.pi_salgrade AS sg ON em.emp_salgrade_id = sg.salgrade_id
LEFT OUTER JOIN
dbo.tbl_emp_status AS es ON em.emp_status = es.StatusID
LEFT OUTER JOIN
dbo.pi_skills AS s ON em.emp_no = s.emp_no
LEFT OUTER JOIN
dbo.pi_location AS L1
INNER JOIN
dbo.pi_lochistory AS Lh ON L1.loc_id = Lh.loc_id ON em.emp_no = Lh.emp_no
LEFT OUTER JOIN
dbo.pi_education ed ON em.emp_no = ed.emp_no
LEFT OUTER JOIN
dbo.pi_jobtitle AS j ON em.emp_jobtitle_id = j.jobtitle_id
Yeah, since you're doing a crap ton of Cartesian products with those joins without on clauses, that will cause plenty of what seem like 'repeated values', but are really just the product of the two tables combining sets.