I have the following criteria.
session.CreateCriteria<DomainModels.Models.FreieAbrechnung>()
.CreateAlias("FreieAbrechnungPositionen", "fp", JoinType.LeftOuterJoin)
.Add(Restrictions.Eq("fp.IstAktiv", true))
.Add(Restrictions.Eq("Kunde.ID", kundenId))
.Add(Restrictions.Eq("IstAktiv", true))
.Add(Restrictions.Eq("Abgeschlossen", false))
.SetResultTransformer(CriteriaSpecification.DistinctRootEntity)
.List<DomainModels.Models.FreieAbrechnung>();
So I get this Sql-Statement:
SELECT this_.ID as ID13_1_, this_.Version as Version13_1_,
this_.KundeID as KundeID13_1_, this_.Erstellungsdatum as Erstellu4_13_1_,
this_.Druckdatum as Druckdatum13_1_, this_.Abgeschlossen as Abgeschl6_13_1_,
this_.AbgeschlossenDatum as Abgeschl7_13_1_, this_.IstAktiv as IstAktiv13_1_,
this_.ErstelltDurchID as Erstellt9_13_1_, this_.ErstelltAm as ErstelltAm13_1_,
this_.MutationDurch as Mutatio11_13_1_, this_.MutationAm as MutationAm13_1_,
fp1_.FreieAbrechnungID as FreieAbr3_3_, fp1_.ID as ID3_, fp1_.ID as ID12_0_,
fp1_.Version as Version12_0_, fp1_.FreieAbrechnungID as FreieAbr3_12_0_,
fp1_.KundeID as KundeID12_0_, fp1_.Bezeichnung as Bezeichn5_12_0_,
fp1_.Betrag as Betrag12_0_, fp1_.Erstellungsdatum as Erstellu7_12_0_,
fp1_.MwStSteuerCodeID as MwStSteu8_12_0_, fp1_.IstAktiv as IstAktiv12_0_,
fp1_.ErstelltDurchID as Erstell10_12_0_, fp1_.ErstelltAm as ErstelltAm12_0_,
fp1_.MutationDurch as Mutatio12_12_0_, fp1_.MutationAm as MutationAm12_0_
FROM
FreieAbrechnung this_
left outer join FreieAbrechnungPosition fp1_ on this_.ID=fp1_.FreieAbrechnungID
WHERE
fp1_.IstAktiv = 1 and this_.KundeID = 1 and this_.IstAktiv = 1 and this_.Abgeschlossen = 0
The problem is, that the restrictions fp1_.IstAktiv = 1 is in the where clause. This restrictions have to be in the left outer join. Like this:
left outer join FreieAbrechnungPosition fp1_ on this_.ID=fp1_.FreieAbrechnungID and fp1_.IstAktiv = 1
What should I change in the criteria, that I get the right Sql-Statement?
Thanks,
Dani
To add conditions to the join, you must use HQL instead of criteria.
A rough translation of your query would be:
select f
from FreieAbrechnung f
left join f.FreieAbrechnungPositionen fp with IstAktiv = 1
where f.IsAktiv = 1
... etc
Related
I have a query where I have to add additional criteria to met the needs.
criteria: if [dd.DataDefinitionValueText] = "PA" then the query should only display those who have value "B" in [cs.ClientSupporterRemarks].
I tried to use IF statements in the INNER JOIN but I can't figure it out properly. Do I have to edit the last INNER JOIN or the one before that?
Thanks for any suggestions.
Code:
SELECT
Distinct
c.CSName
,dd.DataDefinitionValueText
,cs.ClientSupporterIsPrimaryContact
,cs.ClientSupporterRemarks
,usr.UserEMail
,usr.UserName
FROM DB_Analysis a
INNER JOIN [dbo].[DB_Projects] pr ON
a.AnalysisProjectID = pr.ProjectID
AND pr.ProjectIsActive = 1
INNER JOIN DB_Clients c on
c.ClientID = pr.ProjectClientID
INNER JOIN [dbo].[DB_ClientSupporters] cs ON
cs.ClientSupporterClientID = c.ClientID
INNER JOIN [dbo].[DB_Users] usr ON
cs.ClientSupporterUserID = usr.UserID
INNER JOIN [dbo].[DB_DataDefinitions] dd ON
cs.ClientSupporterRole = dd.DataDefinitionValueID
AND dd.DataDefinitionName = 'ClientSupporterRole'
WHERE c.ClientIsActive = 1
Condition stating "if Foo then Bar" means that when foo is false, the condition is satisfied, and when foo is true (or false), the condition is satisfied when Bar is true, so:
if Foo is true then Bar must be true
means
WHERE ( NOT FOO OR BAR )
For the query in the question, that means:
WHERE c.ClientIsActive = 1
AND ( dd.DataDefinitionValueTest <> "PA"
OR dd.DataDefinitionValueTest IS NULL -- remove if column is NOT NULL
OR cs.ClientSupporterRemarks = "B" )
For the query in the question, you can also add that extra set of conditions to the dd JOIN, instead of to the WHERE clause, it makes no difference.
INNER JOIN [dbo].[DB_DataDefinitions] dd
ON cs.ClientSupporterRole = dd.DataDefinitionValueID
AND dd.DataDefinitionName = 'ClientSupporterRole'
AND ( dd.DataDefinitionValueTest <> "PA"
OR dd.DataDefinitionValueTest IS NULL -- remove if column is NOT NULL
OR cs.ClientSupporterRemarks = "B" )
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'
I would like to learn if there is any more efficient way to write the query below:
SELECT *
FROM requests srp
INNER JOIN surgeons rpsur
ON rpsur.id = srp.surgeon_id
LEFT OUTER JOIN #usersurgeons usersurgeons
ON usersurgeons.surgeon_id = srp.surgeon_id
LEFT OUTER JOIN surgeons LOsurgeons
ON usersurgeons.surgeon_id = LOsurgeons.id
LEFT OUTER JOIN provsurgeons LOprovsurgeons
ON LOprovsurgeons.id = LOsurgeons.provsurgeon_id
INNER JOIN #selectedsurgeons up
ON up.surgeon_id = rpsur.id
LEFT OUTER JOIN provsurgeons ps
ON ps.id = rpsur.provsurgeon_id
WHERE rpsur.isprimary = 0
AND usersurgeons.isprimary = 0
AND LOsurgeons.isprimary = 0
AND LOprovsurgeons.isprimary = 0
AND up.isprimary = 0
AND ps.isprimary = 0
I am not happy with the where clause here, is there any more professional way to write this, rather than adding the clauses to the join lines (such as on xx.id = yy.id and xx.isPrimary=0)??
From this query alone there are not many things that can be said. You should consider adding some more context (how do you get data into those temporary tables and the structure of %surgeons tables):
1) Select * makes almost impossible to use any index and also provides a lot of columns (Requests.*, surgeons.*, Provsurgeons.* etc.) in your final result. Return only the columns that you need.
2) If isPrimary = 0 filtering is performed often in your queries (not just this one), you can consider creating a view that fetches data filtered by isPrimary = 0. E.g. vwSurgeons, vwProvsurgeons. Then, you can just JOIN directly to the view instead of the table.
3) [already mentioned in the comments] Any condition that excludes NULL values for the OUTER JOINed table will transform the OUTER into INNER.
Instead of joining all tables and having a where clause at the end, use a derived tables only with filtered records. This way your query performance will be better.
SELECT *
FROM requests srp
INNER JOIN surgeons rpsur
ON rpsur.id = srp.surgeon_id
LEFT OUTER JOIN
(
SELECT *
FROM #usersurgeons
WHERE isprimary = 0
)usersurgeons
ON usersurgeons.surgeon_id = srp.surgeon_id
LEFT OUTER JOIN
(
SELECT *
FROM surgeons
WHERE isprimary = 0
)LOsurgeons
ON usersurgeons.surgeon_id = LOsurgeons.id
LEFT OUTER JOIN
(
SELECT *
FROM provsurgeons
WHERE isprimary = 0
)LOprovsurgeons
ON LOprovsurgeons.id = LOsurgeons.provsurgeon_id
INNER JOIN
(
SELECT *
FROM #selectedsurgeons
WHERE isprimary = 0
)up
ON up.surgeon_id = rpsur.id
LEFT OUTER JOIN
(
SELECT *
FROM provsurgeons
WHERE isprimary = 0
) ps
ON ps.id = rpsur.provsurgeon_id
WHERE rpsur.isprimary = 0
Here's the structure of my database (used to collect info from a survey):
question_responses->answer_choices->subquestions->questions->survey
| ^
V |
submissions->response_group<----------------------------survey_deployment
where A->B means A has the PK of B
So, I want to get the responses of a particular user; let's say that his submission pk is 1. I had written the query
select question_responses.answer_text
from submissions join question_responses on (question_responses.submission_pk = submission.pk)
join answer_choices on (question_responses.answer_choices_pk = answer_choices.pk)
join subquestions on (answer_choices.subquestions_pk = subquestions.pk)
right join questions on (subquestions.questions_pk = questions.pk)
where submissions.pk = 1
order by questions.order
It is possible to not answer questions. In such a case, there is no question_responses.pk recorded. I would still like to be able to account for skipping, so I need this record to be returned, even if there is no response. I thought that the right join would have accounted for this record, but apparently not.
Any help is greatly appreciated.
Because you have submissions.pk = 1 in the where clause this effectively turns your outer join into an inner join, since any missing submission will have a pk of null. and null = 1 is not true.
You could rewrite your query using a LEFT JOIN, and selecting from questions:
select question_responses.answer_text
from questions
left join (subquestions
inner join answer_choices
on answer_choices.subquestions_pk = subquestions.pk
inner join question_responses
on question_responses.answer_choices_pk = answer_choices.pk
inner join submissions
on question_responses.submission_pk = submission.pk)
on subquestions.questions_pk = questions.pk
and submissions.pk = 1
order by questions.order;
This is similar to doing something like:
select subquery.answer_text
from questions
left join
( select question_responses.answer_text, subquestions.questions_pk
from subquestions
inner join answer_choices
on answer_choices.subquestions_pk = subquestions.pk
inner join question_responses
on question_responses.answer_choices_pk = answer_choices.pk
inner join submissions
on question_responses.submission_pk = submission.pk
where submissions.pk = 1
) subquery
on subquery.questions_pk = questions.pk
order by questions.order;
but depending on your dbms the former may perform better as it has no derived tables.
Check out this, does it help?
SELECT question_responses.answer_text
FROM questions LEFT JOIN subquestions on (subquestions.questions_pk = questions.pk)
LEFT JOIN answer_choices on (answer_choices.subquestions_pk = subquestions.pk)
LEFT JOIN question_responses on (question_responses.answer_choices_pk = answer_choices.pk)
LEFT JOIN submissions on (question_responses.submission_pk = submission.pk)
WHERE submissions.pk = 1
ORDER BY questions.order
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.