Need to understand multiple joins correctly - sql

I was trying to join 3 tables - CurrentProducts, SalesInvoice and SalesInvoiceDetail. SalesInvoiceDetail contains FK/foreign key to the other two tables and some other columns. The first query is ok but the second is not. My question comes at the end of the code.
Right
select *
from CurrentProducts inner join
(dbo.SalesInvoiceDetail inner join dbo.SalesInvoice
on dbo.SalesInvoiceDetail.InvoiceID = dbo.SalesInvoice.InvoiceID
)
on dbo.SalesInvoiceDetail.ProductID = dbo.CurrentProducts.ProductID
Wrong
select *
from CurrentProducts inner join
(select * from
dbo.SalesInvoiceDetail inner join dbo.SalesInvoice
on dbo.SalesInvoiceDetail.InvoiceID = dbo.SalesInvoice.InvoiceID
)
on dbo.SalesInvoiceDetail.ProductID = dbo.CurrentProducts.ProductID
error - Incorrect syntax near the keyword 'on'.
Why is the second query wrong ? Isn't it conceptually the same as the first one ? That is inside join makes a result set. We select * the result set and then join this result set to CurrentProducts ?

The first query is a "plain" join expressed with an older syntax. It can be rewritten as:
select
*
from
CurrentProducts
inner join dbo.SalesInvoiceDetail
on dbo.SalesInvoiceDetail.ProductID = dbo.CurrentProducts.ProductID
inner join dbo.SalesInvoice
on dbo.SalesInvoiceDetail.InvoiceID = dbo.SalesInvoice.InvoiceID
The second query is a join where the second table is a subquery. When you join on a subquery, you must assign an alias to it and use that alias to refer to the columns returned by the subquery:
select
*
from
CurrentProducts
inner join (select *
from dbo.SalesInvoiceDetail
inner join dbo.SalesInvoice
on SalesInvoiceDetail.InvoiceID = SalesInvoice.InvoiceID
) as foo on foo.ProductID = dbo.CurrentProducts.ProductID

You need to alias the inner query. Also, in the first one the parentheses are not needed.
select *
from CurrentProducts inner join
(select * from
dbo.SalesInvoiceDetail inner join dbo.SalesInvoice
on dbo.SalesInvoiceDetail.InvoiceID = dbo.SalesInvoice.InvoiceID
) A
on A.ProductID = dbo.CurrentProducts.ProductID

Related

Passing different column values to where clause

SELECT pims.icicimedicalexaminerreport.id,
pims.icicimerfemaleapplicant.adversemenstrualid,
pims.icicimerfemaleapplicant.pregnantid,
pims.icicimerfemaleapplicant.miscarriageabortionid,
pims.icicimerfemaleapplicant.breastdiseaseid,
pims.pimscase.tiannumber
FROM pims.pimscase
INNER JOIN pims.digitization
ON pims.pimscase.digitizationid = pims.digitization.id
INNER JOIN pims.medicalexaminerreport
ON pims.digitization.medicalexaminerreportid =
pims.medicalexaminerreport.id
INNER JOIN pims.icicimedicalexaminerreport
ON pims.medicalexaminerreport.id =
pims.icicimedicalexaminerreport.id
INNER JOIN pims.icicimerfemaleapplicant
ON pims.icicimedicalexaminerreport.id =
pims.icicimerfemaleapplicant.id
WHERE pims.pimscase.tiannumber = 'ICICI1234567890'
which gives me the following output
Now I want to use the above output values to select the rows from the table "YesNoAnswerWithObservation"
I imagine it should look something like this Select * from YesNoAnswerWithObservation Where Id in (22,27,26,...23)
Only instead of typing the values inside IN clause I want to use the values in each column resulting from above-mentioned query.
I tried the below code but it returns all the rows in the table rather than rows mentioned inside the In
SELECT pims.yesnoanswerwithobservation.observation,
graphitegtccore.yesnoquestion.description,
pims.yesnoanswerwithobservation.id ObservationId
FROM pims.yesnoanswerwithobservation
INNER JOIN graphitegtccore.yesnoquestion
ON pims.yesnoanswerwithobservation.yesnoanswerid =
graphitegtccore.yesnoquestion.id
WHERE EXISTS (SELECT pims.icicimedicalexaminerreport.id,
pims.icicimerfemaleapplicant.adversemenstrualid,
pims.icicimerfemaleapplicant.pregnantid,
pims.icicimerfemaleapplicant.pelvicorgandiseaseid,
pims.icicimerfemaleapplicant.miscarriageabortionid,
pims.icicimerfemaleapplicant.gynocologicalscanid,
pims.icicimerfemaleapplicant.breastdiseaseid,
pims.pimscase.tiannumber
FROM pims.pimscase
INNER JOIN pims.digitization
ON pims.pimscase.digitizationid =
pims.digitization.id
INNER JOIN pims.medicalexaminerreport
ON pims.digitization.medicalexaminerreportid =
pims.medicalexaminerreport.id
INNER JOIN pims.icicimedicalexaminerreport
ON pims.medicalexaminerreport.id =
pims.icicimedicalexaminerreport.id
INNER JOIN pims.icicimerfemaleapplicant
ON pims.icicimedicalexaminerreport.id =
pims.icicimerfemaleapplicant.id
WHERE pims.pimscase.tiannumber = 'ICICI1234567890')
Any help or a nudge in the right direction would be greatly appreciated
Presumably you want the ids from the first query:
SELECT awo.observation, ynq.description, ynq.id as ObservationId
FROM pims.yesnoanswerwithobservation awo JOIN
graphitegtccore.yesnoquestion ynq
ON awo.yesnoanswerid = ynq.id
WHERE ynq.id = (SELECT mer.id
FROM pims.pimscase c JOIN
pims.digitization d
ON c.digitizationid = d.id JOIN
pims.medicalexaminerreport mer
ON d.medicalexaminerreportid = mer.id JOIN
pims.icicimedicalexaminerreport imer
ON mer.id = imer.id JOIN
pims.icicimerfemaleapplicant ifa
ON imer.id = ifa.id
WHERE c.tiannumber = 'ICICI1234567890'
) ;
Notice that table aliases make the query much easier to write and to read.

Cannot get both records with SQL/Bigquery JOINs

I've got a query that returns order details, I want information from the briisk table for deals it has found. I also want it to display orders even if the briisk table has nothing.
If I add the final line (and flostream.briisk.master = "") my query only returns one result instead of two.
SELECT *
FROM (SELECT orderno,ifnull(dealid,sales_rule) as DealIDCombo from flostream.orders left join mobileheads.surveys on mobileheads.surveys.order_number = flostream.orders.externalreference) as first
INNER JOIN flostream.orders on first.orderno = flostream.orders.orderno
LEFT JOIN flostream.briisk on first.dealidcombo = flostream.briisk.uniquereference
WHERE first.orderno in (359692,359683)
//AND flostream.briisk.master = ""
When you use a left outer join, then you need to include filter conditions on the second table in the on clause. So try this:
SELECT *
FROM (SELECT orderno,ifnull(dealid,sales_rule) as DealIDCombo
from flostream.orders left join
mobileheads.surveys
on mobileheads.surveys.order_number = flostream.orders.externalreference
) as first INNER JOIN
flostream.orders
on first.orderno = flostream.orders.orderno LEFT JOIN
flostream.briisk
on first.dealidcombo = flostream.briisk.uniquereference AND
flostream.briisk.master = ""
WHERE first.orderno in (359692, 359683)
Conditions on the first table should go in the WHERE clause.

Nested SQL - Distinct Load Left Join in one statement

I wanted to left join two queries:
First:
SELECT TIG_TOL.sName AS Maschine,
TIG_TOL.lTolRef,
Max(TIG_JOB.tActBegin) AS MaxvontActBegin
FROM TIG_JOB LEFT JOIN TIG_TOL ON TIG_JOB.lMacRef = TIG_TOL.lTolRef
WHERE (((TIG_JOB.sState)="Run" Or (TIG_JOB.sState)="Ready"))
GROUP BY TIG_TOL.sName, TIG_TOL.lTolRef;
Second:
SELECT TIG_JOB.sName AS Auftrag,
TIG_JOB.lJobRef,
TIG_TOL.sName AS Artikel,
TIG_TOL.sDescript AS Artikel_Bezeichnung
FROM (TIG_JOB LEFT JOIN TIG_TOL_BOK ON TIG_JOB.lJobRef = TIG_TOL_BOK.lJobRef)
LEFT JOIN TIG_TOL ON (TIG_TOL_BOK.lTolRef = TIG_TOL.lTolRef)
AND (TIG_TOL_BOK.lTolTypRef = TIG_TOL.lTolTypRef)
WHERE (((TIG_TOL.lTolTypRef)=10));
Over a left join
on First.MaxvontActBegin = Second.TIG_JOB.tActBegin
AND First.TIG_TOL.lTolRef = Second.TIG_JOB.lMacRef
Is that possible? In Access Im doing it over two queries, where the second is using the first..
I (blindly) added TIG_JOB.tActBegin and TIG_JOB.lMacRef to the 2nd SELECT (hoping they exist) in order to JOIN the two results.
I used SELECT * only because you did not specify the column selection.
SELECT *
FROM
(
SELECT TIG_TOL.sName AS Maschine,
TIG_TOL.lTolRef,
Max(TIG_JOB.tActBegin) AS MaxvontActBegin
FROM TIG_JOB LEFT JOIN TIG_TOL ON TIG_JOB.lMacRef = TIG_TOL.lTolRef
WHERE (((TIG_JOB.sState)="Run" Or (TIG_JOB.sState)="Ready"))
GROUP BY TIG_TOL.sName, TIG_TOL.lTolRef
) AS FirstTable
LEFT JOIN
(
SELECT TIG_JOB.sName AS Auftrag,
TIG_JOB.lJobRef,
TIG_TOL.sName AS Artikel,
TIG_TOL.sDescript AS Artikel_Bezeichnung,
TIG_JOB.tActBegin,
TIG_JOB.lMacRef
FROM (TIG_JOB LEFT JOIN TIG_TOL_BOK ON TIG_JOB.lJobRef = TIG_TOL_BOK.lJobRef)
LEFT JOIN TIG_TOL ON (TIG_TOL_BOK.lTolRef = TIG_TOL.lTolRef)
AND (TIG_TOL_BOK.lTolTypRef = TIG_TOL.lTolTypRef)
WHERE (((TIG_TOL.lTolTypRef)=10))
) AS SecondTable
ON FirstTable.MaxvontActBegin = SecondTable.tActBegin
AND FirstTable.lTolRef = SecondTable.lMacRef`

syntax error in from clause in access

Below is my query and it says syntax error in from clause whereas it is perfectly working in SQL.After the error 'AS' is highlighted
SELECT
Table1.*,
emp_details_full1.*
FROM Table1
LEFT JOIN
((SELECT
iss_personal_detail.Specialization,
iss_personal_detail.New_rank,
iss_personal_detail.Induction_tr,
iss_personal_detail.Title,
iss_personal_detail.f_name,
iss_personal_detail.m_name,
iss_personal_detail.l_name,
iss_personal_detail.Father_Hus_Name,
iss_personal_detail.Category,
iss_personal_detail.Community,
iss_personal_detail.SEX,
iss_personal_detail.source_recruit,
iss_personal_detail.Pay_Parity,
iss_personal_detail.[Date_Pay_Parity],
iss_personal_detail.UPSC_Rank,
iss_personal_detail.dob,
iss_personal_detail.doj_govt,
iss_personal_detail.DOA_ISS,
iss_personal_detail.Batch,
iss_personal_detail.Year_of_Exam,
iss_personal_detail.Native_Distt,
iss_personal_detail.Native_State,
iss_personal_detail.[Highest Qualification],
iss_personal_detail.Languages_Known,
iss_personal_detail.Mother_Toung,
iss_personal_detail.Marital_Status,
iss_personal_detail.E_mail_ID,
iss_personal_detail.retire_reason,
iss_personal_detail.title_m,
Present_Posting.*,
ISS_MINISTRY_CODE_LIST.*,
ISS_DEPARTMENT_CODE_LIST.*,
ISS_CITY_CODE_LIST.*,
Desig_Code.*,
Grade_Code.Grade_code
FROM ISS_CITY_CODE_LIST
INNER JOIN( Grade_Code
INNER JOIN (Desig_Code
INNER JOIN (((iss_personal_detail
INNER JOIN Present_Posting
ON iss_personal_detail.OID = Present_Posting.OID)
INNER JOIN ISS_MINISTRY_CODE_LIST
ON Present_Posting.ministry = ISS_MINISTRY_CODE_LIST.MINISTRY_CODE)
INNER JOIN ISS_DEPARTMENT_CODE_LIST
ON Present_Posting.department = ISS_DEPARTMENT_CODE_LIST.DEPARTMENT_CODE)
ON Desig_Code.Code = Present_Posting.designation)
ON Grade_Code.Grade_code = Present_Posting.Grade)
ON ISS_CITY_CODE_LIST.city_code=Present_Posting.office_city
)) AS emp_details_full1 ON
(emp_details_full1.DEPARTMENT_CODE=Table1.department) AND
(emp_details_full1.MINISTRY_CODE=Table1.ministry) AND
(emp_details_full1.city_code=Table1.city) AND
(emp_details_full1.Grade_Code=Table1.grade)
WHERE Table1.grade='02';
The first thing I would do is take the inner select and create a view from it.
This will provide a simple, easy to read, easy to debug sql code.
CREATE VIEW emp_details_full1
AS
SELECT iss_personal_detail.Specialization, iss_personal_detail.New_rank,
iss_personal_detail.Induction_tr, iss_personal_detail.Title,
iss_personal_detail.f_name, iss_personal_detail.m_name,
iss_personal_detail.l_name, iss_personal_detail.Father_Hus_Name,
iss_personal_detail.Category, iss_personal_detail.Community,
iss_personal_detail.SEX, iss_personal_detail.source_recruit,
iss_personal_detail.Pay_Parity, iss_personal_detail.[Date_Pay_ Parity],
iss_personal_detail.UPSC_Rank, iss_personal_detail.dob,
iss_personal_detail.doj_govt, iss_personal_detail.DOA_ISS,
iss_personal_detail.Batch, iss_personal_detail.Year_of_Exam,
iss_personal_detail.Native_Distt, iss_personal_detail.Native_State,
iss_personal_detail.[Highest Qualification],
iss_personal_detail.Languages_Known,
iss_personal_detail.Mother_Toung, iss_personal_detail.Marital_Status,
iss_personal_detail.E_mail_ID, iss_personal_detail.retire_reason,
iss_personal_detail.title_m, Present_Posting., ISS_MINISTRY_CODE_LIST.,
ISS_DEPARTMENT_CODE_LIST., ISS_CITY_CODE_LIST., Desig_Code.*,
Grade_Code.Grade_code
FROM ISS_CITY_CODE_LIST INNER JOIN( Grade_Code INNER JOIN (Desig_Code INNER JOIN
(((iss_personal_detail INNER JOIN Present_Posting ON iss_personal_detail.OID =
Present_Posting.OID) INNER JOIN ISS_MINISTRY_CODE_LIST
ON Present_Posting.ministry = ISS_MINISTRY_CODE_LIST.MINISTRY_CODE)
INNER JOIN ISS_DEPARTMENT_CODE_LIST ON
Present_Posting.department = ISS_DEPARTMENT_CODE_LIST.DEPARTMENT_CODE) ON
Desig_Code.Code = Present_Posting.designation) ON Grade_Code.Grade_code =
Present_Posting.Grade)
ON ISS_CITY_CODE_LIST.city_code=Present_Posting.office_city
Then the rest of the sql would look like this:
SELECT Table1.,emp_details_full1.
FROM Table1 LEFT JOIN emp_details_full1
ON (emp_details_full1.DEPARTMENT_CODE=Table1.department) AND
(emp_details_full1.MINISTRY_CODE=Table1.ministry) AND
(emp_details_full1.city_code=Table1.city) AND
(emp_details_full1.Grade_Code=Table1.grade) WHERE Table1.grade='02';
Now, if you look closely, you can see that there is a closing bracket missing between the end of the ON clause and the start of the WHERE clause.
So to fix that:
SELECT Table1.,emp_details_full1.
FROM Table1 LEFT JOIN emp_details_full1
ON (emp_details_full1.DEPARTMENT_CODE=Table1.department) AND
(emp_details_full1.MINISTRY_CODE=Table1.ministry) AND
(emp_details_full1.city_code=Table1.city) AND
(emp_details_full1.Grade_Code=Table1.grade)) WHERE Table1.grade='02';
Isn't that much easier to work with?

Recursive query with outer joins?

I'm attempting the following query,
DECLARE #EntityType varchar(25)
SET #EntityType = 'Accessory';
WITH Entities (
E_ID, E_Type,
P_ID, P_Name, P_DataType, P_Required, P_OnlyOne,
PV_ID, PV_Value, PV_EntityID, PV_ValueEntityID,
PV_UnitValueID, PV_UnitID, PV_UnitName, PV_UnitDesc, PV_MeasureID, PV_MeasureName, PV_UnitValue,
PV_SelectionID, PV_DropDownID, PV_DropDownName, PV_DropDownOptionID, PV_DropDownOptionName, PV_DropDownOptionDesc,
RecursiveLevel
)
AS
(
-- Original Query
SELECT dbo.Entity.ID AS E_ID, dbo.EntityType.Name AS E_Type,
dbo.Property.ID AS P_ID, dbo.Property.Name AS P_Name, DataType.Name AS P_DataType, Required AS P_Required, OnlyOne AS P_OnlyOne,
dbo.PropertyValue.ID AS PV_ID, dbo.PropertyValue.Value AS PV_Value, dbo.PropertyValue.EntityID AS PV_EntityID, dbo.PropertyValue.ValueEntityID AS PV_ValueEntityID,
dbo.UnitValue.ID AS PV_UnitValueID, dbo.UnitOfMeasure.ID AS PV_UnitID, dbo.UnitOfMeasure.Name AS PV_UnitName, dbo.UnitOfMeasure.Description AS PV_UnitDesc, dbo.Measure.ID AS PV_MeasureID, dbo.Measure.Name AS PV_MeasureName, dbo.UnitValue.UnitValue AS PV_UnitValue,
dbo.DropDownSelection.ID AS PV_SelectionID, dbo.DropDown.ID AS PV_DropDownID, dbo.DropDown.Name AS PV_DropDownName, dbo.DropDownOption.ID AS PV_DropDownOptionID, dbo.DropDownOption.Name AS PV_DropDownOptionName, dbo.DropDownOption.Description AS PV_DropDownOptionDesc,
0 AS RecursiveLevel
FROM dbo.Entity
INNER JOIN dbo.EntityType ON dbo.EntityType.ID = dbo.Entity.TypeID
INNER JOIN dbo.Property ON dbo.Property.EntityTypeID = dbo.Entity.TypeID
INNER JOIN dbo.PropertyValue ON dbo.Property.ID = dbo.PropertyValue.PropertyID AND dbo.PropertyValue.EntityID = dbo.Entity.ID
INNER JOIN dbo.DataType ON dbo.DataType.ID = dbo.Property.DataTypeID
LEFT JOIN dbo.UnitValue ON dbo.UnitValue.ID = dbo.PropertyValue.UnitValueID
LEFT JOIN dbo.UnitOfMeasure ON dbo.UnitOfMeasure.ID = dbo.UnitValue.UnitOfMeasureID
LEFT JOIN dbo.Measure ON dbo.Measure.ID = dbo.UnitOfMeasure.MeasureID
LEFT JOIN dbo.DropDownSelection ON dbo.DropDownSelection.ID = dbo.PropertyValue.DropDownSelectedID
LEFT JOIN dbo.DropDownOption ON dbo.DropDownOption.ID = dbo.DropDownSelection.SelectedOptionID
LEFT JOIN dbo.DropDown ON dbo.DropDown.ID = dbo.DropDownSelection.DropDownID
WHERE dbo.EntityType.Name = #EntityType
UNION ALL
-- Recursive Query?
SELECT E2.E_ID AS E_ID, dbo.EntityType.Name AS E_Type,
dbo.Property.ID AS P_ID, dbo.Property.Name AS P_Name, DataType.Name AS P_DataType, Required AS P_Required, OnlyOne AS P_OnlyOne,
dbo.PropertyValue.ID AS PV_ID, dbo.PropertyValue.Value AS PV_Value, dbo.PropertyValue.EntityID AS PV_EntityID, dbo.PropertyValue.ValueEntityID AS PV_ValueEntityID,
dbo.UnitValue.ID AS PV_UnitValueID, dbo.UnitOfMeasure.ID AS PV_UnitID, dbo.UnitOfMeasure.Name AS PV_UnitName, dbo.UnitOfMeasure.Description AS PV_UnitDesc, dbo.Measure.ID AS PV_MeasureID, dbo.Measure.Name AS PV_MeasureName, dbo.UnitValue.UnitValue AS PV_UnitValue,
dbo.DropDownSelection.ID AS PV_SelectionID, dbo.DropDown.ID AS PV_DropDownID, dbo.DropDown.Name AS PV_DropDownName, dbo.DropDownOption.ID AS PV_DropDownOptionID, dbo.DropDownOption.Name AS PV_DropDownOptionName, dbo.DropDownOption.Description AS PV_DropDownOptionDesc,
(RecursiveLevel + 1)
FROM Entities AS E2
INNER JOIN dbo.Entity ON dbo.Entity.ID = E2.PV_ValueEntityID
INNER JOIN dbo.EntityType ON dbo.EntityType.ID = dbo.Entity.TypeID
INNER JOIN dbo.Property ON dbo.Property.EntityTypeID = dbo.Entity.TypeID
INNER JOIN dbo.PropertyValue ON dbo.Property.ID = dbo.PropertyValue.PropertyID AND dbo.PropertyValue.EntityID = E2.E_ID
INNER JOIN dbo.DataType ON dbo.DataType.ID = dbo.Property.DataTypeID
INNER JOIN dbo.UnitValue ON dbo.UnitValue.ID = dbo.PropertyValue.UnitValueID
INNER JOIN dbo.UnitOfMeasure ON dbo.UnitOfMeasure.ID = dbo.UnitValue.UnitOfMeasureID
INNER JOIN dbo.Measure ON dbo.Measure.ID = dbo.UnitOfMeasure.MeasureID
INNER JOIN dbo.DropDownSelection ON dbo.DropDownSelection.ID = dbo.PropertyValue.DropDownSelectedID
INNER JOIN dbo.DropDownOption ON dbo.DropDownOption.ID = dbo.DropDownSelection.SelectedOptionID
INNER JOIN dbo.DropDown ON dbo.DropDown.ID = dbo.DropDownSelection.DropDownID
)
SELECT E_ID, E_Type,
P_ID, P_Name, P_DataType, P_Required, P_OnlyOne,
PV_ID, PV_Value, PV_EntityID, PV_ValueEntityID,
PV_UnitValueID, PV_UnitID, PV_UnitName, PV_UnitDesc, PV_MeasureID, PV_MeasureName, PV_UnitValue,
PV_SelectionID, PV_DropDownID, PV_DropDownName, PV_DropDownOptionID, PV_DropDownOptionName, PV_DropDownOptionDesc,
RecursiveLevel
FROM Entities
INNER JOIN [dbo].[Entity] AS dE
ON dE.ID = PV_EntityID
The problem is the second query, the "recursive one" is getting the data I expect since I can't do the LEFT JOINs like in the first query. (At least to my understanding).
If I remove the fetching of the data that requires the LEFT (Outer) JOINs then the recursion works perfectly. My problem is I need both. Is there a way I can accomplish this?
Per http://msdn.microsoft.com/en-us/library/ms175972.aspx you can not have a left/right/outer join in a recursive CTE.
For a recursive CTE you can't use a subquery either so I sugest following this example.
They use two CTE's. The first is not recursive and does the left join to get the data it needs. The second CTE is recursive and inner joins on the first CTE. Since CTE1 is not recursive it can left join and supply default values for the missing rows and is guarenteed to work in the inner join.
However, you can also duplicate a left join with a union and subselect though it isn't really useful normally but it is interesting.
In that case, you would keep your first statement how it is. It will match all rows that join successfully.
Then UNION that query with another query that removes the join, but has a
NOT EXISTS(SELECT 1 FROM MISSING_ROWS_TABLE WHERE MAIN_TABLE.JOIN_CONDITION = MISSING_ROWS_TABLE.JOIN_CONDITION)
This gets all the rows that failed the previous join condition in query 1. You can replace the colmuns you would get from MISSING_ROWS_TABLE with NULL. I had to do this once using a coding framework that didn't support outer joins. Since recursive CTE's don't allow subqueries you have to use the first solution.