LEFT JOIN not returning NULL - sql

I guess the problem comes down to this: what are some extreme scenarios where using a LEFT OUTER JOIN DOES NOT return the values as expected? Because in the result set I'm expecting the fields I joined on (item and ID) + any NULL values where the rows don't match, but item and ID don't show up.
Info:
qry_HersheySAPMaxDate2 returns 95 rows.
qry_HersheySAPMaxDate2 could have NULL values for MaxOfMaxOfjob_Date, SumOfSumOfqty_on_hand, product_code, and whse, whereas ID and item will always have a value.
qry_HersheySAPMaxDate3 returns 85 rows.
qry_HersheySAPMaxDate3 does not have any NULL values in any field, but excludes 10 id and item rows.
The query:
SELECT
qry_HersheySAPMaxDate3.ID,
qry_HersheySAPMaxDate3.item,
qry_HersheySAPMaxDate3.MaxOfMaxOfjob_date, qry_HersheySAPMaxDate3.SumOfSumOfqty_on_hand, qry_HersheySAPMaxDate3.product_code,
qry_HersheySAPMaxDate3.whse,
qry_HersheySAPMaxDate3.jobnumber
FROM
qry_HersheySAPMaxDate2
LEFT JOIN qry_HersheySAPMaxDate3 ON (qry_HersheySAPMaxDate2.item = qry_HersheySAPMaxDate3.item) AND (qry_HersheySAPMaxDate2.ID = qry_HersheySAPMaxDate3.ID);
Result set using my query + the suggestion in one of the answers to use LEFT OUTER JOIN instead:
Screenshot

You complain about your query producing entirely blank rows. Let's see why:
You outer join qry3 to qry2. That means when there is no match for a qry2 record in qry3, then a pseudo qry3 record with all columns set to null gets joined.
In your query you select only fields from qry3, so in an outer join case they are all null. Select qry2.ID and qry2.item instead of qry3.ID and qry3.item to see the values that have no match:
SELECT
qry_HersheySAPMaxDate2.ID,
qry_HersheySAPMaxDate2.item,

You should use LEFT OUTER JOIN if you want the NULL values to be included in the result

Related

Oracle - MINUS-operator with different results than OUTER JOIN

In Oracle the following MINUS SQL statement returns results, while the allegedly equivalent OUTER JOIN statement doesn't return any.
Results:
SELECT
/*+parallel (8)*/
pd.item_id
FROM MY_TABLE#DB_LINK_PROD_ENV
WHERE pd.valid_to='09.09.9999'
MINUS
SELECT
/*+parallel (8)*/
it.item_id
FROM MY_TABLE#DB_LINK_TEST_ENV
WHERE it.valid_to='09.09.9999' ;
No results:
SELECT
/*+parallel (8)*/
pd.item_id,
it.item_id
FROM MY_TABLE#DB_LINK_PROD_ENV
LEFT OUTER JOIN MY_TABLE#DB_LINK_TEST_ENV
ON pd.item_id = it.item_id
WHERE it.valid_to ='09.09.9999'
AND pd.valid_to ='09.09.9999'
AND it.item_id IS NULL;
Without knowing the data, what could be the reason?
In first query it is MINUS. Means it will show all item_id present in DB_LINK_PROD_ENV having valid_to='09.09.9999' but not present in DB_LINK_TEST_ENV having valid_to='09.09.9999'.
In second one it is LEFT JOIN with AND condition.
it.valid_to ='09.09.9999'
AND pd.valid_to ='09.09.9999'
So it is possible that there are records in DB_LINK_PROD_ENV having valid_to='09.09.9999' but NO any record in DB_LINK_TEST_ENV with valid_to='09.09.9999'.
So when you will perform MINUS in first query, it will show record present in DB_LINK_PROD_ENV. But in second query AND condition will fail to give you any record.

what is the difference between these two queries

I have written two queries to check the differences between two tables, both shown below. Query 2 shows me the correct results.
In each table there is one record that is not in the other. So I wanted a query which would show both these records, which Query 2 does. It show me the 90 rows where the tables match plus another 2 rows, one where a record is in tblIH but not in tblTempN and another record which is in tblTempN but not in tblIH.
Whereas Query 1 shows me only the 90 records where the tables match and one extra row where the record is in tblIH but not in tblTempN - it does NOT however show me the record in tblTempN which is not in tblIH - why? I thought using a full outer join would show me all records from both tables? I don't really understand the difference between the two queries as they seem the same to me?
Query 1
select coalesce(h.Sedol, nav.Sedol) Sedol,
coalesce(nav.Name, h.Name) Name,
isnull(h.Nominal, 0) - isnull(nav.Nominal, 0) NomDiff
from tblIH h full outer join tblTempN nav
on h.Sedol = nav.Sedol and h.Code = nav.Code
where h.FundCode = 'ABC' and h.DatePrice = '2015-03-20'
Query 2
;with hld as
(
select Sedol, Name, FX, Nominal from tblIH
where DatePrice = '2015-03-20' and FundCode = 'ABC'
), nav as
(
select Sedol, Name, Nominal from tblTempN
where DateAcc = '2015-03-20' and FundCode = 'ABC'
)
select coalesce(hld.Sedol, nav.Sedol) Sedol,
coalesce(nav.Name, hld.Name) Name,
isnull(hld.Nominal, 0) - isnull(nav.Nominal, 0) NomDiff
from hld full outer join nav
on hld.Sedol = nav.Sedol
In full outer join if you don't have satisfied condition field values from that table fetched as null
I suppose you missed to write conditions
nav.FundCode = 'ABC' and nav.DatePrice = '2015-03-20'
but apart from this you are missing one more fundamental that where clause will be applicable on the result from that full outer join.
So actually you are getting 90+1+1 out of full outer join but your where condition is filtering one record from this result because for one desired record h.FundCode and h.DatePrice value is NULL.
You can use NVL function while checking for these condition.

WHERE clause and LEFT JOIN in SQL Server query

I have this query:
SELECT
EnrollmentID, MarketID
FROM
Contracts AS CO
LEFT JOIN
Customers AS C ON C.EnrollmentID = CO.BatchID AND MarketID = 'AB'
WHERE
C.EnrollmentID IS NULL
Here, I have a question that in this query is it possible that the query will verify data for MarketID = 'AB' in left join because as per WHERE condition?
I am getting result of EnrollmentIDs and MarketIDs are all NULL.
Note: The LEFT JOIN keyword returns all the rows from the left table (Contracts ), even if there are no matches in the right table (Customers ).
Now, if you want to select right table column and there are no matching data in the right table ,like.
SELECT CO.EnrollmentID, CO.MarketID ,C.Some_col
FROM Contracts AS CO
LEFT JOIN Customers AS C ON C.EnrollmentID = CO.BatchID
so, C.Some_col column will get all the null value for no matching rows in the right table.i think this is the reason why you are getting the null value for
MarketIDs and EnrollmentIDs.
hope, this help you.

JOIN Tables with all specified fields matching

I have two tables. I'm selecting all the values in the first table and trying to get the associated rows in the second table which match BOTH of the specified fields.
So in this example, I want only the rows in the CarsTable and the associated columns in the TrucksTable in which BOTH the Tires and Windows values match (if just one value matches, I don't want it). I'm not even certain a join is the correct operation. Any ideas?
SELECT * FROM CarsTable, TrucksTable
LEFT JOIN TrucksTable t1
ON
t1.Tires = Cars.Tires
LEFT JOIN Trucks t2
ON
t2.Windows = Cars.Windows
You need to do some research on joins...your from clause is all over the place. Carstable,truckstable as you have here is a cross join..and I don't understand what the left joins you are doing are. I think you only have two tables:
SELECT c.*, t.* FROM CarsTable c
inner join TrucksTable t
on t.tires = c.tires and t.windows = c.windows
inner join will function as a filter...if the record in carstable finds no matches in the truckstable by the keys listed, it won't appear. If you want all cartable rows even those that find no match, use left join (in this case, t.* will be null)

Trouble with tsql not in query

I'm trying to find rows where a value in table 1 column A are not in table 2 column A
This is the query...
SELECT contactsid
FROM contacts
WHERE (email1 NOT IN (SELECT email
FROM old_contact))
It returns 0 rows, which I know is incorrect. There are many rows in contacts.email1 that are not in old_contact.email
How should I be writing this query?
My guess is that old_contract.email takes on a NULL value.
For this reason, not exists is often a better choice:
SELECT contactsid
FROM contacts c
WHERE NOT EXISTS (SELECT 1
FROM old_contract oc
WHERE c.email = oc.email1
) ;
You could also add where email1 is not null to the subquery. However, I find just using not exists is generally safer in case I forget that condition.
Try:
SELECT contactsid
FROM Contacts a
LEFT JOIN old_contact b
ON a.email1 = b.email
WHERE b.email IS NULL
This will join Contacts to old_contact using a LEFT JOIN -- a type of join that, based on the join condition, returns all records from the left side (i.e. Contacts) even if no records exist on the right side. Then, the WHERE clause filters the results so that it returns only the records from the left side where the ride side records don't exist.