Access left join not working as I am picturing it - sql

I am trying to write a query that involves 3 tables and left joining two of them onto a main one.
SELECT UNIT_MAIN.UNIT_NO, DEPT_MAIN.LEV_2, Card.CardNumberLong AS [Some
Number], Card.Enabled, F_CARD.CARD_NO, F_CARD.END_DT
FROM (((UNIT_MAIN
INNER JOIN DEPT_MAIN ON UNIT_MAIN.USING_DEPT = DEPT_MAIN.DEPT_ID)
LEFT JOIN Card ON (UNIT_MAIN.UNIT_NO = Card.UnitCode AND Card.Enabled = True) )
LEFT JOIN F_CARD ON (UNIT_MAIN.UNIT_ID = F_CARD.ASSIGNED_ID AND (F_CARD.END_DT) Is Null ))
WHERE (((UNIT_MAIN.STATUS)="A") AND ((DEPT_MAIN.LEV_2)="AM") AND ((Card.Enabled)=True) )
OR (((UNIT_MAIN.STATUS)="D") AND ((DEPT_MAIN.LEV_2)="AM") AND ((Card.Enabled)=True) )
The issue I am having is when F_CARD table has rows where the F_CARD.END_DT is not null, causing the main table (unit table) not to show up even though it is a left join and the F_CARD table rows did not satisfy the join condition (or I am to believe).
I don't have any where clauses on the F_CARD table and they are only on the join condition.
edit
When I perform
LEFT JOIN MFIVE_F_CARD ON (MFIVE_UNIT_DEPT_COMP_MAIN.UNIT_ID = MFIVE_F_CARD.ASSIGNED_ID AND ((MFIVE_F_CARD.END_DT) Is Null)
The unit does not appear if the F_CARD table contained rows that had an END_DT, I was to believe that since the left join condition failed, the inner table (unit table) should appear regardless.
If I remove any F_CARD related values from the query, the missing units I am looking for appear. It is an inner join, left join, left join. When the second left join happens, I lose rows even when they should appear.
I narrowed down my joins and just did the inner with the left with F_CARD. Trying to see why it doesnt return rows where the join fails.
Tried to do the following, however im getting an unsupported join error...
SELECT
UNIT_MAIN.UNIT_NO
,DEPT_MAIN.LEV_2
,Card.CardNumberLong AS [SomeNumber]
,Card.Enabled
,F_CARD.CARD_NO
,F_CARD.END_DT FROM
(
(
(
UNIT_MAIN
INNER JOIN DEPT_MAIN
ON UNIT_MAIN.USING_DEPT = DEPT_MAIN.DEPT_ID
)
LEFT JOIN Card
ON (UNIT_MAIN.UNIT_NO = Card.UnitCode AND Card.Enabled = True)
)
LEFT JOIN F_CARD
ON (UNIT_MAIN.UNIT_ID = F_CARD.ASSIGNED_ID AND F_CARD.END_DT Is Null)
) WHERE
(UNIT_MAIN.STATUS = "A" OR UNIT_MAIN.STATUS = "D")
AND DEPT_MAIN.LEV_2 = "AM"
Thanks.

I have a feeling it's because you have clauses in your joins that are doing boolean checks rather than matching records between the tables, i.e.
Card.Enabled = True and (F_CARD.END_DT) IS NULL
Try changing the query to:
SELECT
UNIT_MAIN.UNIT_NO
,DEPT_MAIN.LEV_2
,Card.CardNumberLong AS [SomeNumber]
,Card.Enabled
,F_CARD.CARD_NO
,F_CARD.END_DT
FROM
(
(
(
UNIT_MAIN
INNER JOIN DEPT_MAIN
ON UNIT_MAIN.USING_DEPT = DEPT_MAIN.DEPT_ID
)
LEFT JOIN Card
ON UNIT_MAIN.UNIT_NO = Card.UnitCode
)
LEFT JOIN F_CARD
ON UNIT_MAIN.UNIT_ID = F_CARD.ASSIGNED_ID
)
WHERE
(UNIT_MAIN.STATUS = "A" OR UNIT_MAIN.STATUS = "D")
AND DEPT_MAIN.LEV_2 = "AM"
AND Card.Enabled = True

Related

Speed up SQL query performance with nested queries

Could anyone help me speed this query up? It currently take 17 minutes to run but does return the correct data and it populates a subform in MS Access. Functions in the rest of the VBA are declared as long to try to speed up more.
Here's the full query:
SELECT lots of things
FROM (((((((((((((((ngstest
INNER JOIN patients
ON ngstest.internalpatientid = patients.internalpatientid)
INNER JOIN referral
ON ngstest.referralid = referral.referralid)
INNER JOIN checker
ON ngstest.bookby = checker.check1id)
INNER JOIN ngspanel
ON ngstest.ngspanelid = ngspanel.ngspanelid)
LEFT JOIN ngspanel AS ngspanel_1
ON ngstest.ngspanelid_b = ngspanel_1.ngspanelid)
INNER JOIN status
ON ngstest.statusid = status.statusid)
INNER JOIN dbo_patient_table
ON patients.patientid = dbo_patient_table.patienttrustid)
LEFT JOIN dna
ON ngstest.dna = dna.dnanumber)
INNER JOIN status AS status_1
ON patients.s_statusoverall = status_1.statusid)
LEFT JOIN gw_gendertable
ON dbo_patient_table.genderid = gw_gendertable.genderid)
LEFT JOIN ngswesbatch
ON ngstest.wesbatch = ngswesbatch.ngswesbatchid)
LEFT JOIN checker AS checker_1
ON ngstest.check1id = checker_1.check1id)
LEFT JOIN checker AS checker_2
ON ngstest.check2id = checker_2.check1id)
LEFT JOIN checker AS checker_3
ON ngstest.check3id = checker_3.check1id)
LEFT JOIN ngspanel AS ngspanel_2
ON ngstest.ngspanelid_c = ngspanel_2.ngspanelid)
LEFT JOIN checker AS checker_4
ON ngstest.check4id = checker_4.check1id
WHERE ((ngstest.referralid IN
(SELECT referralid FROM referral
WHERE grouptypeid = 14)
AND ngstest.ngstestid IN
(SELECT ngstest.ngstestid
FROM ngsanalysis
INNER JOIN ngstest
ON ngsanalysis.ngstestid = ngstest.ngstestid
WHERE ngsanalysis.pedigree = 3302) )
AND status.statusid = 1202218800)
ORDER BY ngstest.priority,
ngstest.daterequested;
The two nested queries are strings from elsewhere in the code so are called in the vba as " & includereferralls & " And " & ParentsStatusesFilter & "
They are:
ParentsStatusesFilter = "NGSTest.NGSTestID in
(SELECT NGSTest.NGSTestID
FROM NGSAnalysis
INNER JOIN NGSTest
ON NGSAnalysis.NGSTestID = NGSTest.NGSTestID
WHERE NGSAnalysis.Pedigree IN (3302,3303,3304)"
And
includereferrals = "NGSTest.ReferralID
(SELECT referralid FROM referral WHERE referral.grouptypeid = 14)"
The query needs to remain readable (and therefore editable) so can't use things like Distinct, Group By or contain any Unions. Have tried Exists instead of In for the nested queries but that stops it from actually filtering the results.
WHERE EXISTS (SELECT NGSTest.NGSTestID
FROM NGSAnalysis
INNER JOIN NGSTest
ON NGSAnalysis.NGSTestID = NGSTest.NGSTestID
WHERE NGSAnalysis.Pedigree IN (3302,3303,3304)
So the exist clause you have there isn't tied to the outer query which would run similar to just added 1 = 1 to the where clause. I took your where clause and converted it. It should look something like this...
WHERE EXISTS (
SELECT referralid
FROM referral
WHERE grouptypeid = 14 AND ngstest.referralid = referral.referralid)
AND EXISTS (
SELECT ngsanalysis.ngstestid
FROM ngsanalysis
WHERE ngsanalysis.pedigree IN (3302,3303,3304) AND ngstest.ngstestid = ngsanalysis.ngstestid
)
AND status.statusid = 1202218800
Adding exists will speed it up a bit, but the the bulk of the slowness is the left joins. Access does not handle the left joins as well as SQL Server does. Change all your joins to inner joins and you will see the query runs very fast. This is obviously not ideal since some relationships are optional. What I have done to get around this is add a default record that replaces a null relationship.
Here is what that looks like for you: In the checker table you could add a record that represents a null value. So put a record into the checker table with check1id of -1 or 0. Then default check1id, check2id, check3id on ngstest to -1 or 0. You will need to do that type of thing for all tables you need to left join on.

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.

Select statement where joins causing records to be excluded

I have the below query with multiple joins.The last 3 joins are required to get the g.fin_id value. This works fine (see results) BUT because some records in the ACCUM_ISS_CHAR_HIST table have e.char9_nme values of NULL, it excludes the records in the results altogether. So it seems as when the e.char9_nme value has a record then it will produce a result, but as soon as it has a Null value then it is excluded. I would still like to see the records even though the g.fin_id for those will then be blank because they have a e.char9_nme value of Null. How can I change the query to accomplish this?
select
a.acct_id,
c.fld3_txt,
b.issue_loc1_cde,
b.instr_id,
a.fld1_nme,
b.issue_cls2_nme,
g.fin_id,
e.char9_nme
from position_dg as a
inner join
infoportal..issue_dg as b on b.INSTR_ID = a.INSTR_ID
inner join
InfoPortal..IVW_ACCT as c on a.acct_id = c.acct_id
inner join
InfoPortal..DW_AcctCharDG as d on a.acct_id = d.acctid
inner join
ACCUM_ISS_CHAR_HIST as e on a.instr_id = e.instr_id
inner join
MD_FINANCIAL_ENTITY as f on e.char9_nme = f.fin_enty_name
inner join md_FINANCIAL_ENTITY_ALTERNATE_IDENTIFIER as g on
f.fin_enty_id = g.fin_enty_id
and b.MAT_EXP_DTE > getdate()
and b.issue_cls1_nme = 'Derivatives'
and a.as_of_tms >= getdate()-1
and b.iss_typ in ('FFX','IRS','EQF')
and d.AcctChrSetId = 'DerivativeRpt'
and d.EndTms IS NULL
and a.acct_id = 'FOGEMBLCR'
and g.id_ctxt_typ = 'LEGAL_ENTITY_IDENTIFIER'
and e.as_of_dte = (
select MAX (as_of_dte)-1
from accum_iss_char_hist
)
I expect the results to show fin_id records for some ond blank fin_id records for some, but at the moment only the ones with a fin_id record is hown and the rest is excluded from the results.
You are looking for a left join.
Join all those tables (last 3 as you said) as left join. For better clarity I have moved conditions of every tables in their ON clause and for base table a made a where clause.
select
a.acct_id,
c.fld3_txt,
b.issue_loc1_cde,
b.instr_id,
a.fld1_nme,
b.issue_cls2_nme,
g.fin_id,
e.char9_nme
from position_dg as a
inner join
infoportal..issue_dg as b on b.INSTR_ID = a.INSTR_ID
and b.MAT_EXP_DTE > getdate()
and b.issue_cls1_nme = 'Derivatives'
and b.iss_typ in ('FFX','IRS','EQF')
inner join
InfoPortal..IVW_ACCT as c on a.acct_id = c.acct_id
inner join
InfoPortal..DW_AcctCharDG as d on a.acct_id = d.acctid
and d.AcctChrSetId = 'DerivativeRpt'
and d.EndTms IS NULL
left join
ACCUM_ISS_CHAR_HIST as e on a.instr_id = e.instr_id
and e.as_of_dte = (
select MAX (as_of_dte)-1
from accum_iss_char_hist
)
left join
MD_FINANCIAL_ENTITY as f on e.char9_nme = f.fin_enty_name
left join
md_FINANCIAL_ENTITY_ALTERNATE_IDENTIFIER as g on f.fin_enty_id = g.fin_enty_id
and g.id_ctxt_typ = 'LEGAL_ENTITY_IDENTIFIER'
Where a.as_of_tms >= getdate()-1
and a.acct_id = 'FOGEMBLCR'

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.

LEFT JOIN ON COALESCE(a, b, c) - very strange behavior

I have encountered very strange behavior of my query and I wasted a lot of time to understand what causes it, in vane. So I am asking for your help.
SELECT count(*) FROM main_table
LEFT JOIN front_table ON front_table.pk = main_table.fk_front_table
LEFT JOIN info_table ON info_table.pk = front_table.fk_info_table
LEFT JOIN key_table ON key_table.pk = COALESCE(info_table.fk_key_table, front_table.fk_key_table_1, front_table.fk_key_table_2)
LEFT JOIN side_table ON side_table.fk_front_table = front_table.pk
WHERE side_table.pk = (SELECT MAX(pk) FROM side_table WHERE fk_front_table = front_table.pk)
OR side_table.pk IS NULL
Seems like a simple join query, with coalesce, I've used this technique before(not too many times) and it worked right.
In this query I don't ever get nulls for side_table.pk. If I remove coalesce or just don't use key_table, then the query returns rows with many null side_table.pk, but if I add coalesce join, I can't get those nulls.
It seems key_table and side_table don't have anything in common, but the result is so weird.
Also, when I don't use side_table and WHERE clause, the count(*) result with coalesce and without differs, but I can't see any pattern in rows missing, it seems random!
Real query:
SELECT ECHANGE.EXC_AUTO_KEY, STOCK_RESERVATIONS.STR_AUTO_KEY FROM EXCHANGE
LEFT JOIN WO_BOM ON WO_BOM.WOB_AUTO_KEY = EXCHANGE.WOB_AUTO_KEY
LEFT JOIN VIEW_WO_SUB ON VIEW_WO_SUB.WOO_AUTO_KEY = WO_BOM.WOO_AUTO_KEY
LEFT JOIN STOCK stock3 ON stock3.STM_AUTO_KEY = EXCHANGE.STM_AUTO_KEY
LEFT JOIN STOCK stock2 ON stock2.STM_AUTO_KEY = EXCHANGE.ORIG_STM
LEFT JOIN CONSIGNMENT_CODES con2 ON con2.CNC_AUTO_KEY = stock2.CNC_AUTO_KEY
LEFT JOIN CONSIGNMENT_CODES con3 ON con3.CNC_AUTO_KEY = stock3.CNC_AUTO_KEY
LEFT JOIN CI_UTL ON CI_UTL.CUT_AUTO_KEY = EXCHANGE.CUT_AUTO_KEY
LEFT JOIN PART_CONDITION_CODES pcc2 ON pcc2.PCC_AUTO_KEY = stock2.PCC_AUTO_KEY
LEFT JOIN PART_CONDITION_CODES pcc3 ON pcc3.PCC_AUTO_KEY = stock3.PCC_AUTO_KEY
LEFT JOIN STOCK_RESERVATIONS ON STOCK_RESERVATIONS.STM_AUTO_KEY = stock3.STM_AUTO_KEY
LEFT JOIN WAREHOUSE wh2 ON wh2.WHS_AUTO_KEY = stock2.WHS_ORIGINAL
LEFT JOIN SM_HISTORY ON (SM_HISTORY.STM_AUTO_KEY = EXCHANGE.ORIG_STM AND SM_HISTORY.WOB_REF = EXCHANGE.WOB_AUTO_KEY)
LEFT JOIN RC_DETAIL ON stock3.RCD_AUTO_KEY = RC_DETAIL.RCD_AUTO_KEY
LEFT JOIN RC_HEADER ON RC_HEADER.RCH_AUTO_KEY = RC_DETAIL.RCH_AUTO_KEY
LEFT JOIN WAREHOUSE wh3 ON wh3.WHS_AUTO_KEY = COALESCE(RC_DETAIL.WHS_AUTO_KEY, stock3.WHS_ORIGINAL, stock3.WHS_AUTO_KEY)
WHERE STOCK_RESERVATIONS.STR_AUTO_KEY = (SELECT MAX(STR_AUTO_KEY) FROM STOCK_RESERVATIONS WHERE STM_AUTO_KEY = stock3.STM_AUTO_KEY)
OR STOCK_RESERVATIONS.STR_AUTO_KEY IS NULL
Removing LEFT JOIN WAREHOUSE wh3 gives me about unique EXC_AUTO_KEY values with a lot of NULL STR_AUTO_KEY, while leaving this row removes all NULL STR_AUTO_KEY.
I recreated simple tables with numbers with the same structure and query works without any problems o.0
I have a feeling COALESCE is acting as a REQUIRED flag for the joined table, hence shooting the LEFT JOIN to become an INNER JOIN.
Try this:
SELECT COUNT(*)
FROM main_table
LEFT JOIN front_table ON front_table.pk = main_table.fk_front_table
LEFT JOIN info_table ON info_table.pk = front_table.fk_info_table
LEFT JOIN key_table ON key_table.pk = NVL(info_table.fk_key_table, NVL(front_table.fk_key_table_1, front_table.fk_key_table_2))
LEFT JOIN (SELECT fk_, MAX(pk) as pk FROM side_table GROUP BY fk_) st ON st.fk_ = front_table.pk
NVL might behave just the same though...
I undertood what was the problem (not entirely though): there is a LEFT JOIN VIEW_WO_SUB in original query, 3rd line. It causes this query to act in a weird way.
When I replaced the view with the other table which contained the information I needed, the query started returning right results.
Basically, with this view join, NVL, COALESCE or CASE join with combination of certain arguments did not work along with OR clause in WHERE subquery, all rest was fine. ALthough, I could get the query to work with this view join, by changing the order of joined tables, I had to place table participating in where subquery to the bottom.