I have the following query:
SELECT
pupils.txtSchoolID, pupils.txtPreName, pupils.txtSurname,
pupils.txtForm, pupils.txtAdditionalHealth, pupils.txtAllergyNotes,
notes.txtNote
FROM
TblPupilManagementPupils AS pupils
LEFT OUTER JOIN
TblPupilManagementHealthNotes AS notes ON pupils.txtSchoolID = notes.txtSchoolID
I need to only pull the notes.txtNote when notes.txtType = 'Dietary', however, when I set this in a WHERE clause, I only get entries with Type Dietary, I still need all of the pupil's table data also. I thought the left outer join would do this.
When setting the WHERE clause, I try
WHERE notes.txtType = 'Dietary'
but this also does not work, I have been setting as a parameter temporarily.
you have to remove where clause and put that condition on clause because
Logically, all JOINs are performed as INNER JOINs using the ON filters, and then, as a subsequent step, any OUTER JOIN rows are added back to the necessary side. After all JOINs are complete is the WHERE filter processed. as a result when you applied it on where it removed all expect Dietary values records
SELECT pupils.txtSchoolID, pupils.txtPreName, pupils.txtSurname,
pupils.txtForm, pupils.txtAdditionalHealth, pupils.txtAllergyNotes,
notes.txtNote
FROM TblPupilManagementPupils AS pupils LEFT OUTER JOIN
TblPupilManagementHealthNotes AS notes
ON pupils.txtSchoolID = notes.txtSchoolID and notes.txtType = 'Dietary'
Put the condition (notes.txtType = 'Dietary') with ON clause :
. . .
FROM TblPupilManagementPupils AS pupils LEFT OUTER JOIN
TblPupilManagementHealthNotes AS notes
ON pupils.txtSchoolID = notes.txtSchoolID AND notes.txtType = 'Dietary';
If you filter the LEFT OUTER JOINED table data with WHERE clause, then you are making a join as INNER JOIN instead of LEFT JOIN.
Alternatively less optimized route is; run your query as is with no where clause and no additional on clause. Insert data into temp table and then filter that data as so; where notes.txtType = #Param . and this #Param you declare topside for stored procedure or query as #Param varchar(200) to capture whatever expected front end value your expecting.
Related
Using Microsoft T-SQL, I know there is a difference in the result set between putting a filter in the join verses putting the filter in the where clause, because I get a different row count, and its hard to pin point, because it is a complex query with thousands of rows.
So does anybody know how this might lead to different results?
I feel safer with the where clause, but I am curious why the other one didn't get the same results.
Select
.....
left outer join
datamart_agent ag on a.CUSTOMER_TKN = ag.customer_tkn
and a.CUSTOMER_ACCT_TKN = ag.customer_acct_tkn
and a.ACCOUNT_PKG_TKN = ag.account_pkg_tkn
--where (commented out)
and ag.TYPE_DESC = 'Agent'
versus
Select
.....
left outer join
datamart_agent ag on a.CUSTOMER_TKN = ag.customer_tkn
and a.CUSTOMER_ACCT_TKN = ag.customer_acct_tkn
and a.ACCOUNT_PKG_TKN = ag.account_pkg_tkn
where
--and (commented out)
ag.TYPE_DESC = 'Agent'
If condition is in your where clause then it will drop all records for which no match was found. It is a like an eraser. I deletes all records for which no match was found (Type_Desc is null).
The safer thing, if you are actually seeking left join, is to put the condition in the on clause. If there was no match, it will still come in the result. When Type_Desc is null, it means you don't know who the agent is, but if you don't know, you don't want to delete the record....
I have the same query on two databases, but in the first database it finds me data, while in the second one it does not. Is it possible to build on these two bases so that I can filter all those that exist in the first base and not the second. These are my sql query:
use firstDB;
SELECT A_ANSPRECHPARTNER.AAS_ID FROM A_ANSPRECHPARTNER LEFT OUTER JOIN A_ADRESSEN ON A_ANSPRECHPARTNER.AAS_ADR_ID = A_ADRESSEN.ADR_ID WHERE ADR_Nr = 106740
use secondDB;
SELECT A_ANSPRECHPARTNER.AAS_ID FROM A_ANSPRECHPARTNER LEFT OUTER JOIN A_ADRESSEN ON A_ANSPRECHPARTNER.AAS_ADR_ID = A_ADRESSEN.ADR_ID WHERE ADR_Nr = 106740
the current result
If these databases are on the same server you can put each of your queries in a subquery specifying the database name when referencing the table. Then left join the subquery on firstDB to the subquery on secondDB filtering the records where there is a record in firstDB, but not in secondDB.
SELECT DB_1.*
FROM (
SELECT A_ANSPRECHPARTNER.AAS_ID
FROM firstDB.dbo.A_ANSPRECHPARTNER
LEFT OUTER JOIN firstDB.dbo.A_ADRESSEN ON A_ANSPRECHPARTNER.AAS_ADR_ID = A_ADRESSEN.ADR_ID
) DB_1
LEFT JOIN (
SELECT A_ANSPRECHPARTNER.AAS_ID
FROM secondDB.dbo.A_ANSPRECHPARTNER
LEFT OUTER JOIN secondDB.dbo.A_ADRESSEN ON A_ANSPRECHPARTNER.AAS_ADR_ID = A_ADRESSEN.ADR_ID
) DB_2 ON DB_1.ADR_Nr = DB_2.ADR_Nr
WHERE DB_2.ADR_Nr IS NULL
AND DB_1.ADR_Nr = 106740
You can just remove the AND DB_1.ADR_Nr = 106740 in order to find all records in firstDB that are not in secondDB. If these databases are on different servers you would have to set up a linked server and add that to the beginning of your table reference.
I have a query like this:
return $this->createQueryBuilder('supervision')
->join('supervision.supervisionEvents', 'supervisionEvents')
->andWhere('supervisionEvents.episode = :episode')
->setParameter('episode', $episode)
->getQuery()
->getResult()
;
I want to get all supervisions but the supervisionEvents I want to filter.
In result I only want to have SupervisionEvents with episode = :episode.
I used join, leftJoin and innerJoin. Nothing works like desired.
I tried to have a condition on the join:
->innerJoin('s.supervisionEvents', 'supervisionEvent', 'WITH', 'supervisionEvent.episode = :episode')
But thats also not working!
You are actually pretty close. You want to filter only on the join, so use a left join with condition to the join clause:
return $this->createQueryBuilder('supervision')
->addSelect('supervisionEvents')
->leftJoin('supervision.supervisionEvents', 'supervisionEvents', Join::WITH, 'supervisionEvents.episode = :episode')
->setParameter('episode', $episode)
->getQuery()
->getResult()
;
It is needed also to select the joined relation, so that it is hydrated on the result.
References
doctrine left join with condition
Why and when a LEFT JOIN with condition in WHERE clause is not equivalent to the same LEFT JOIN in ON
I need to find the items that exist in table A but not in table B. Now that would be really simple in MySQL doing a join like this
select * from A
left join B on A.key=B.key
where B.key is null
However for some reason this is not working in MSSQL. I have created the query without the where clause to see all the results and I only see matches, not null values. Do you have any idea why this is not working?
I know I can alternatively use "when not exists" but I want to know the reason as to why with a join is not working.
I am adding the code for your review
select Absences.CustomerID, b.*
from (
select * from openquery(JUAN_INTERFACE,'select cmp_wwn from Planet_Customers where i_outcome =4')) b
left join Absences on Absences.CustomerID = b.cmp_wwn
where Absences.Type = 3223
Your where clause is filtering out null values:
where Absences.Type = 3223
You are left-joining from the openquery subquery to Absences; and then filtering only rows that have a specific (non-null) value in an Absences column.
Did you mean to join the other way around, from Absenses to openquery?
I was having a problem with a larger query in SQL Server which I traced back to this section of code which isn't performing as expected.
SELECT item_name,item_num,rst_units
FROM tbl_item left join tbl_sales_regional on item_num=rst_item
WHERE rst_month=7 and rst_customer='AB123'
The first table (tbl_item) has 10,000 records. The second table (tbl_sales_regional) has 83 for the shown criteria.
Instead of returning 10,000 records with 9,917 nulls, the execution plan shows SQL Server has rewritten as an inner join and consequently returns 83 results.
In order to achieve the intended result, I have to join off a subquery. Can someone provide an explanation why this doesn't work?
Not sure which fields belong where, but you seem to have some fields from tbl_sales_regional in your WHERE condition.
Move them into the ON clause:
SELECT item_name, item_num, rst_units
FROM tbl_item
LEFT JOIN
tbl_sales_regional
ON rst_item = item_num
AND rst_month = 7
AND rst_customer = 'AB123'
The WHERE clause operates on the results of the join so these conditions cannot possibly hold true for any NULL records from tbl_sales_regional returned by the join, as NULL cannot be equal to anything.
That's why the optimizer transforms your query into the inner join.
Any conditions you have in your WHERE clause are applied regardless of the left join, effectively making it an inner join.
You need to change it to:
SELECT item_name,item_num,rst_units
FROM tbl_item left join tbl_sales_regional on item_num=rst_item
AND rst_month=7 and rst_customer='AB123'