Conditional Inner Join with two Functions - sql

I have two functions. I need to decide whether to join with these two based on a BIT Value.
ON APEL.data_Period_dataination_Lookup_ID = CCEL.data_Period_dataination_Lookup_ID
INNER JOIN markcommon.GetPredecessordatadataIds() AS PIDS
IF #Combined_Flag=1
BEGIN
ON PIDS.data_Period_dataination_Identifier = APEL.data_Period_dataination_Identifier
AND PIDS.data_Period_Identifier = APL.data_Period_Identifier
END
Basically
if BIT=0 join with function 1 else join with function 2
I tried putting an IF Clause .. but it does not seem to work. What is the proper way to do it?

Just add your static condition as part of the join condition and use a LEFT JOIN to ensure it works with the missing row. You can then use a case expression in your select to obtain the correct column e.g.
SELECT
CASE WHEN F1.id IS NOT NULL THEN F1.MyColumn ELSE F2.MyColumn END
FROM ...
LEFT JOIN markcommon.Function1() AS F1
ON #Combined_Cohort = 1
AND {The rest of the join conditions}
LEFT JOIN markcommon.Function2() AS F2
ON #Combined_Cohort = 0
AND {The rest of the join conditions}

I think you can just use a LEFT JOIN:
ON APEL.data_Period_dataination_Lookup_ID = CCEL.data_Period_dataination_Lookup_ID LEFT JOIN
markcommon.GetPredecessordatadataIds() PIDS
ON #Combined_Cohort = 1 AND
PIDS.data_Period_dataination_Identifier = APEL.data_Period_dataination_Identifier AND
PIDS.data_Period_Identifier = APL.data_Period_Identifier
. . .
WHERE #Combined_Cohort <> 1 OR PIDS.data_Period_dataination_Identifier IS NOT NULL

You can use the LEFT JOIN as follows:
APEL.data_Period_dataination_Lookup_ID = CCEL.data_Period_dataination_Lookup_ID
LEFT JOIN markcommon.GetPredecessordatadataIds() AS PIDS
ON (#Combined_Flag=1 AND PIDS.data_Period_dataination_Identifier = APEL.data_Period_dataination_Identifier
AND PIDS.data_Period_Identifier = APL.data_Period_Identifier
)
LEFT JOIN FUNCTION2() AS PIDS2
ON (#Combined_Flag=0 AND <<join condition for function 2>>
)

Please also check:
SELECT
IIF(F1.id IS NOT NULL,F1.MyColumn,F2.MyColumn)
FROM ...
LEFT JOIN markcommon.Function1() AS F1
ON #Combined_Cohort = 1
AND {The rest of the join conditions}
LEFT JOIN markcommon.Function2() AS F2
ON #Combined_Cohort != 1
AND {The rest of the join conditions}

Related

left outer join doesnt return all rows on left table

set #fuel_type='hsd';
select
ro.ro_id,
(case
when if(#fuel_type='ms',r.ms_field_input_id,r.hsd_field_input_id)= 0
then if(#fuel_type='ms',concat(r.remark_ms,r.remark_branded),r.remark_hsd)
else
f.field_name
end )
from
retail_outlets ro left join
volume_trackers r on ro.ro_id=r.ro_id,
field_inputs_master f
where
if(#fuel_type='ms',r.ms_field_input_id = f.field_id,r.hsd_field_input_id=f.field_id)
and ro.pricing_module=1 and if(#fuel_type='ms',ro.ms,ro.hsd)=1 and r.date_inserted='2017-02-06'
;
I need to show all the ro_id in the retail_outlets table but only the ro_id that match with the volume trackers table are displayes
Not positive but I think this is what you're after.
changes are the following:
removed , notation and inject a left join
moved the r.date_inserted to the join criteria.
moved where clause for , join to new left join and altered to case statement as to why I used a left join... Since we tie back to R which is already a left join it made sense to me to continue with left joins...
removed some unneeded ()'s
Assumptions r.date_inserted is a varchar2 data type or '2017-02-06' is implicitly being cast correctly.
.
SET #fuel_type='hsd';
SELECT
ro.ro_id ,
CASE
WHEN IF(#fuel_type='ms',r.ms_field_input_id,r.hsd_field_input_id)= 0
THEN IF(#fuel_type='ms',concat(r.remark_ms,r.remark_branded),r.remark_hsd)
ELSE f.field_name
END
FROM retail_outlets ro
LEFT JOIN volume_trackers r
ON ro.ro_id = r.ro_id
AND r.date_inserted = '2017-02-06'
LEFT JOIN field_inputs_master f
ON f.field_id = CASE WHEN #fuel_type='ms'
THEN r.ms_field_input_id
ELSE r.hsd_field_input_id
END
WHERE ro.pricing_module=1
AND IF(#fuel_type ='ms',ro.ms,ro.hsd)=1;

SQL Stored Procedure With One To Many Relationship Return Only Most Recent Record

I've been having a terrible time with this. I created a stored procedure to return a corresponding record, but one of the tables has multiple print jobs so it returns multiple records. I only want the most recent requested print job to return and I can't get it to work correctly.
Please help!
SELECT PrintJobs.WORDERKey,
PrintJobs.JobNumber,
WORDER.U_DateRequired AS DateRequired,
ProductMaster.PartFileItemID,
WORDER.ManufacturingDepartment AS MfgDept,
PrintJobs.Copies AS LabelCopies,
PrintJobs.ExpiryDate AS JobExpiryDate,
PrintJobs.Batch,
PrintJobs.JulianDate AS JobJulianDate,
ProductMaster.Description,
ProductMaster.PackFormat,
ProductMaster.IngDec,
ProductMaster.BarCodeNumber,
ProductMaster.CustomerProductCode,
ProductMaster.CriticalInstruction,
ProductMaster.StorageInstruction,
ProductMaster.MixedCaseTitle,
ProductMaster.MixedCode1,
ProductMaster.MixedCode2,
ProductMaster.MixedCode3,
ProductMaster.MixedCode4,
ProductMaster.MixedDescription1,
ProductMaster.MixedDescription2,
ProductMaster.MixedDescription3,
ProductMaster.MixedDescription4,
ProductMaster.MixedIngDec1,
ProductMaster.MixedIngDec2,
ProductMaster.MixedIngDec3,
ProductMaster.MixedIngDec4,
ProductMaster.CookingInstruction,
ProductMaster.LogoFilename,
ProductMaster.ProductExpiryRule,
ExpiryRulesMaster.GS1_AppID,
ProductMaster.LabelTemplateID,
CASE WHEN ProductMaster.PartFileItemID IS NULL THEN 'N' ELSE 'Y' END AS LabelDefExists,
LabelTemplateMaster.FileName,
CASE WHEN [DateFormat] = 'Default' THEN ExpiryRulesMaster.DateFormatString ELSE [DateFormat] END AS DateFormatString,
ExpiryRulesMaster.DateRounding,
ExpiryRulesMaster.ExcludeXmasNewYear,
PART.ExternalShelfLifeTotalDays,
CustomOptions.Tagline,
CustomOptions.ShortName AS CustShortName,
ExpiryRulesMaster.LabelText AS ExpiryRuleLabelText,
ProductMaster.inner_hDescription,
ProductMaster.inner_vDescription,
ProductMaster.inner_CustCode,
ProductMaster.inner_Storage,
ProductMaster.inner_WarningMsg,
ProductMaster.inner_Dateformat,
ProductMaster.inner_SpecialCode,
ProductMaster.LabelType,
ProductMaster.inner_MicroSuiteCode,
ProductMaster.inner_PackWeight,
ProductMaster.inner_JDateFormat,
ProductMaster.CustomOptionID,
ProductMaster.inner_PrintLogo,
PART.NominalWeight,
ProductMaster.IngDec_html,
ProductMaster.IngDec_Active,
PrintJobs.PrintJobsID,
MaxJobs.MaxJob,
PrintJobs.DateEntered
FROM ProductMaster RIGHT OUTER JOIN
(
SELECT Partfileitemid,
--JobNumber,
MAX(dateentered) MaxJob
FROM PrintJobs
GROUP BY PartFileItemID
)
MaxJobs ON ProductMaster.PartFileItemID = MaxJobs.PartFileItemID RIGHT OUTER JOIN
PrintJobs ON PrintJobs.PartFileItemID = MaxJobs.PartFileItemID RIGHT OUTER JOIN
LabelTemplateMaster ON ProductMaster.LabelTemplateID = LabelTemplateMaster.LabelTemplateID LEFT OUTER JOIN
CustomOptions ON ProductMaster.CustomOptionID = CustomOptions.CustomOptionID LEFT OUTER JOIN
ExpiryRulesMaster ON ProductMaster.ProductExpiryRule = ExpiryRulesMaster.ExpiryRule LEFT OUTER JOIN
[F8Extract].[dbo].[WORDER] ON PrintJobs.WORDERKey = WORDER.WORDERKey LEFT OUTER JOIN
[F8Extract].[dbo].[PART] ON ProductMaster.PartFileItemID = Part.PartFileItemID
WHERE PrintJobs.WORDERKey = #WORDERKey
END
Thanks,
Stacy
One way would be to look at TOP and ORDER BY, i.e.
SELECT TOP 1
PrintJobs.WORDERKey,
PrintJobs.JobNumber,
WORDER.U_DateRequired AS DateRequired,
ProductMaster.PartFileItemID,
WORDER.ManufacturingDepartment AS MfgDept,
PrintJobs.Copies AS LabelCopies,
PrintJobs.ExpiryDate AS JobExpiryDate,
PrintJobs.Batch,
PrintJobs.JulianDate AS JobJulianDate,
ProductMaster.Description,
ProductMaster.PackFormat,
ProductMaster.IngDec,
ProductMaster.BarCodeNumber,
ProductMaster.CustomerProductCode,
ProductMaster.CriticalInstruction,
ProductMaster.StorageInstruction,
ProductMaster.MixedCaseTitle,
ProductMaster.MixedCode1,
ProductMaster.MixedCode2,
ProductMaster.MixedCode3,
ProductMaster.MixedCode4,
ProductMaster.MixedDescription1,
ProductMaster.MixedDescription2,
ProductMaster.MixedDescription3,
ProductMaster.MixedDescription4,
ProductMaster.MixedIngDec1,
ProductMaster.MixedIngDec2,
ProductMaster.MixedIngDec3,
ProductMaster.MixedIngDec4,
ProductMaster.CookingInstruction,
ProductMaster.LogoFilename,
ProductMaster.ProductExpiryRule,
ExpiryRulesMaster.GS1_AppID,
ProductMaster.LabelTemplateID,
CASE WHEN ProductMaster.PartFileItemID IS NULL THEN 'N' ELSE 'Y' END AS LabelDefExists,
LabelTemplateMaster.FileName,
CASE WHEN [DateFormat] = 'Default' THEN ExpiryRulesMaster.DateFormatString ELSE [DateFormat] END AS DateFormatString,
ExpiryRulesMaster.DateRounding,
ExpiryRulesMaster.ExcludeXmasNewYear,
PART.ExternalShelfLifeTotalDays,
CustomOptions.Tagline,
CustomOptions.ShortName AS CustShortName,
ExpiryRulesMaster.LabelText AS ExpiryRuleLabelText,
ProductMaster.inner_hDescription,
ProductMaster.inner_vDescription,
ProductMaster.inner_CustCode,
ProductMaster.inner_Storage,
ProductMaster.inner_WarningMsg,
ProductMaster.inner_Dateformat,
ProductMaster.inner_SpecialCode,
ProductMaster.LabelType,
ProductMaster.inner_MicroSuiteCode,
ProductMaster.inner_PackWeight,
ProductMaster.inner_JDateFormat,
ProductMaster.CustomOptionID,
ProductMaster.inner_PrintLogo,
PART.NominalWeight,
ProductMaster.IngDec_html,
ProductMaster.IngDec_Active,
PrintJobs.PrintJobsID,
MaxJobs.MaxJob,
PrintJobs.DateEntered
FROM ProductMaster RIGHT OUTER JOIN
(
SELECT Partfileitemid,
--JobNumber,
MAX(dateentered) MaxJob
FROM PrintJobs
GROUP BY PartFileItemID
)
MaxJobs ON ProductMaster.PartFileItemID = MaxJobs.PartFileItemID RIGHT OUTER JOIN
PrintJobs ON PrintJobs.PartFileItemID = MaxJobs.PartFileItemID RIGHT OUTER JOIN
LabelTemplateMaster ON ProductMaster.LabelTemplateID = LabelTemplateMaster.LabelTemplateID LEFT OUTER JOIN
CustomOptions ON ProductMaster.CustomOptionID = CustomOptions.CustomOptionID LEFT OUTER JOIN
ExpiryRulesMaster ON ProductMaster.ProductExpiryRule = ExpiryRulesMaster.ExpiryRule LEFT OUTER JOIN
[F8Extract].[dbo].[WORDER] ON PrintJobs.WORDERKey = WORDER.WORDERKey LEFT OUTER JOIN
[F8Extract].[dbo].[PART] ON ProductMaster.PartFileItemID = Part.PartFileItemID
WHERE PrintJobs.WORDERKey = #WORDERKey
ORDER BY PrintJobs.Number DESC
Note change the PrintJobs.Number to whatever field specifies the time order.

Avoiding NULL records on this LEFT JOIN

The query below works - EXCEPT - it is returning NULL values for vehicle_id. I do not want any records that have NULL for vehicle_id.
Since vehicle_id is tied to fund_series, this is complicated to me.
When I had the vehicle_id conditions underneath the WHERE, the query was not working. Any SQL geniuses that can help?
I put the MIN() aggregate functions in there just so I could get the GROUP BY to work.
SELECT DISTINCT
MIN(ml.pretty_file_name),
ml.filename,
MIN(ml.issued_date),
MIN(mr.rule_name),
MIN(mlob.line_of_business_name),
MIN(mt.media_type_name),
MAX(v.vehicle_name)
FROM Media_Live ml
JOIN Media_Type mt
ON mt.media_type_id = ml.media_type_id
JOIN Media_Rule mr
ON mr.rule_id = ml.rule_id
JOIN Media_Line_Of_Business mlob
ON mlob.line_of_business_id = ml.line_of_business_id
LEFT JOIN Fund_Class_Media fcm
ON fcm.media_id=ml.media_id
LEFT JOIN Fund_Class_Live fc
ON fc.fund_class_id = fcm.fund_class_id
LEFT JOIN Fund_Series fs
ON fs.fund_series_id = fc.fund_series_id
LEFT JOIN Vehicle AS v
ON v.vehicle_id=fs.vehicle_id AND /*THIS IS WHERE IM GETTING NULLS*/
(
v.vehicle_id = 1
OR v.vehicle_id = 2
OR v.vehicle_id = 5
)
LEFT JOIN Media_Media_Tag AS mmt ON mmt.media_id=ml.media_id
LEFT JOIN Media_Tag AS mtag ON mtag.tag_id=mmt.tag_id
WHERE
(/*people can search with terms for fc*/
--fc.fund_class_id LIKE '%'+replace(?,' ','%')+'%'
)
(
mt.media_type_id = 33
OR mt.media_type_id = 1
OR mt.media_type_id = 12
)
AND
(
mr.rule_id = 3
OR mr.rule_id = 9
)
AND
(
mtag.tag_name != 'exclude_web_lit_center'
)
GROUP BY ml.filename
This is what a left join does, allow nulls. Just take out the left join part making it an inner join.
JOIN Vehicle AS v ON v.vehicle_id=fs.vehicle_id AND v.vehicle_id IN (1,2,5)
You cold also do this, but I don't see why you would:
LEFT JOIN Vehicle AS v ON v.vehicle_id=fs.vehicle_id AND ISNULL(v.vehicle_id,0) IN (1,2,5)
In the WHERE clause, add:
AND v.Vehicl_Id IS NOT NULL
That should do it.

Oracle: LEFT OUTER JOIN with using construct

I can't understand the usage of the using word. Can you explain me?
SELECT 1
FROM CONF_RAGGR_OPZTAR ropt
JOIN TAR_OPZIONI_TARIFFARIE OPT using (OPT_OPZIONE_TARIFFARIA_ID)
JOIN CONF_RAGGRUPPAMENTI_FORN rgf using (RGF_RAGGRUPPAMENTO_FORN_ID)
JOIN CONF_FORNITURE_REL_RAGG forg using (RGF_RAGGRUPPAMENTO_FORN_ID)
JOIN CONF_FORNITURE forn using (FORN_FORNITURA_ID)
LEFT JOIN (
select *
from CONF_ELEMENTI_FATTURABILI
where ELF_FLAG_ANN = 'N'
AND ELF_DATA_VER_FIN = TO_DATE('31/12/9999','DD/MM/YYYY')
) elf **using** (ROPT_RAGGR_OPZTAR_ID,COID_CONTRATTUARIO_ID,ROPT_DATA_INI,EDW_PARTITION)
-- LEFT OUTER JOIN TAR_VOCI_FATTURABILI vof
-- ON (elf.VOF_VOCE_FATTURABILE_ID = vof.VOF_VOCE_FATTURABILE_ID)
-- LEFT OUTER JOIN BASE_FASCE_ORARIE fas
-- ON (fas.FAS_FASCIA_ORARIA_ID = elf.FAS_FASCIA_ORARIA_ID)
WHERE FORN_FORNITURA_ID = 'QJlXmOFZPF3eAlAG'
ORDER BY elf.ELF_VERSIONE DESC;
The using keyword indicates that this is a natural join. This means that the column names on both side of the join are identical.
In your case this means that you will join both sides on ROPT_RAGGR_OPZTAR_ID, COID_CONTRATTUARIO_ID, ROPT_DATA_INI and EDW_PARTITION.

Using left join and inner join in the same query

Below is my query using a left join that works as expected. What I want to do is add another table filter this query ever further but having trouble doing so. I will call this new table table_3 and want to add where table_3.rwykey = runways_updatable.rwykey. Any help would be very much appreciated.
SELECT *
FROM RUNWAYS_UPDATABLE
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
'*************EDIT To CLARIFY *****************
Here is the other statement that inner join i would like to use and I would like to combine these 2 statements.
SELECT *
FROM RUNWAYS_UPDATABLE A, RUNWAYS_TABLE B
WHERE A.RWYKEY = B.RWYKEY
'***What I have so far as advice taken below, but getting syntax error
SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.*, AIRPORT_RUNWAYS_SELECTED.*
FROM RUNWAYS_UPDATABLE
INNER JOIN AIRPORT_RUNWAYS_SELECTED
ON RUNWAYS_UPDATABLE.RWYKEY = AIRPORT_RUNWAYS_SELECTED.RWYKEY
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
NOTE: If i comment out the inner join and leave the left join or vice versa, it works but when I have both of joins in the query, thats when im getting the syntax error.
I always come across this question when searching for how to make LEFT JOIN depend on a further INNER JOIN. Here is an example for what I am searching when I am searching for "using LEFT JOIN and INNER JOIN in the same query":
SELECT *
FROM foo f1
LEFT JOIN (bar b1
INNER JOIN baz b2 ON b2.id = b1.baz_id
) ON
b1.id = f1.bar_id
In this example, b1 will only be included if b2 is also found.
Remember that filtering a right-side table in left join should be done in join itself.
select *
from table1
left join table2
on table1.FK_table2 = table2.id
and table2.class = 'HIGH'
I finally figured it out. Thanks for all your help!!!
SELECT * FROM
(AIRPORT_RUNWAYS_SELECTED
INNER JOIN RUNWAYS_UPDATABLE
ON AIRPORT_RUNWAYS_SELECTED.RWYKEY = RUNWAYS_UPDATABLE.RWYKEY)
LEFT JOIN TURN_UPDATABLE ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
Add your INNER_JOIN before your LEFT JOIN:
SELECT *
FROM runways_updatable ru
INNER JOIN table_3 t3 ON ru.rwykey = t3.rwykey
LEFT JOIN turn_updatable tu
ON ru.rwykey = tu.rwykey
AND (tu.airline_code IS NULL OR tu.airline_code = '' OR tu.airline_code = '')
WHERE ru.icao = 'ICAO'
AND (ru.tora > 4000 OR ru.lda > 0)
If you LEFT JOIN before your INNER JOIN, then you will not get results from table_3 if there is no matching row in turn_updatable. It's possible this is what you want, but since your join condition for table_3 only references runways_updatable, I would assume that you want a result from table_3, even if there isn't a matching row in turn_updatable.
EDIT:
As #NikolaMarkovinović pointed out, you should filter your LEFT JOIN in the join condition itself, as you see above. Otherwise, you will not get results from the left-side table (runways_updatable) if that condition isn't met in the right-side table (turn_updatable).
EDIT 2: OP mentioned this is actually Access, and not MySQL
In Access, perhaps it's a difference in the table aliases. Try this instead:
SELECT [ru].*, [tu].*, [ars].*
FROM [runways_updatable] AS [ru]
INNER JOIN [airport_runways_selected] AS [ars] ON [ru].rwykey = [ars].rwykey
LEFT JOIN [turn_updatable] AS [tu]
ON [ru].rwykey = [tu].rwykey
AND ([tu].airline_code IS NULL OR [tu].airline_code = '' OR [tu].airline_code = '')
WHERE [ru].icao = 'ICAO'
AND ([ru].tora > 4000 OR [ru].lda > 0)
If it is just an inner join that you want to add, then do this. You can add as many joins as you want in the same query. Please update your answer if this is not what you want, though
SELECT *
FROM RUNWAYS_UPDATABLE
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
INNER JOIN table_3
ON table_3.rwykey = runways_updatable.rwykey
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
I am not really sure what you want. But maybe something like this:
SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.*
FROM RUNWAYS_UPDATABLE
JOIN table_3
ON table_3.rwykey = runways_updatable.rwykey
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
For Postgres, query planner does not guarantee order of execution of join. To Guarantee one can use #Gajus solution but the problem arises if there are Where condition for inner join table's column(s). Either one would to require to carefully add the where clauses in the respective Join condition or otherwise it is better to use subquery the inner join part, and left join the output.