When joining 2 tables one table comes up null - sql

I am joining 2 tables on the first table I get all the relevant data on the second table I only get nulls. There are no nulls in either table Can any one tell me why this is happening?
select * from apmast
left join apitem
on apmast.fvendno + apmast.fccompany = apitem.fcinvkey

There is a problem with your ON that's resulting in you not getting matching records. A LEFT JOIN means that you should get all data from the left table and only the matching records from the right table, or else NULL where there are no matching records. The key to the join, however, is the ON statement. Make sure that apmast.fvendno + apmast.fccompany is actually equal to apitem.fcinvkey.

here is a explanation on the types of joins just incase you get stuck in the future.
INNER JOIN this will get only the rows that match in both the FROM clause and the JOINING table.
LEFT OUTER JOIN this gets all the rows from the table specified in the FROM clause and only the rows that match in the JOINING table.
RIGHT OUTER JOIN this gets all the rows from the table specified in the JOIN clause and only the rows that match in the FROM clause.
FULL OUTER JOIN this will get all the rows from both tables.
SELF JOIN this is used when you need to join the table back to its self to return data.

Related

Inner join between two tables with same count values

I have been working on this issue since 2 days now.
I have two tables created by using SQL Select statements
SELECT (
) Target
INNER JOIN
SELECT (
) Source
ON Join condition 1
AND Join condition 2
AND Join condition 3
AND Join condition 4
AND Join condition 5
The target table has count value of 10,000 records.
The source table has count value of 10,000 records.
but when I do an inner join between the two tables on the 5 join conditions
I get 9573 records.
I am basically trying to find a one to one match between source and target table. I feel every field from target matches every field in source.
Questions:
Why does my inner join give less records even if there are same value of records in both tables?
If it is expected, how can I make sure I get the exact 10,000 records after the join condition?
1) An INNER JOIN only outputs the rows from the JOINING of two tables where their joining columns match. So in your case, Join Condition1 may not exist in rows in both tables and therefore some rows are filtering out.
2) As the other poster mentioned a left join is one way. You need to look which table source or target you want to use as your master i.e. start from and return all those rows. You then left join the remaining table based on your conditions to add all the columns where you join conditions match.
It's probably better if you give us the tables you are working on and the query\results you are trying to achieve.
There's some really good articles about the different joins out there. But it looks like you'd be interested in left joins. So if it exists in Target, but not in Source, it will not drop the record.
So, it would be:
SELECT(...) Target
LEFT OUTER JOIN
SELECT(...) Source
ON cond1 and cond2 and cond3 and cond4 and cond5
Give that a shot and let me know how it goes!
Sometime you need to rely on logical analysis rather than feelings. Use this query to find the fields that do not match and then work out your next steps
SELECT
Target.Col1,Source.Col1,
Target.Col2,Source.Col2,
Target.Col3,Source.Col3
FROM
(
) Target
FULL OUTER JOIN
(
) Source
ON Target.Col1=Source.Col1
AND Target.Col2=Source.Col2
AND Target.Col3=Source.Col3
WHERE (
Target.Col1 IS NULL
OR Source.Col1 IS NULL
OR Target.Col2 IS NULL
OR Source.Col2 IS NULL
OR Target.Col3 IS NULL
OR Source.Col3 IS NULL
)

LEFT OUTER JOINs not acting as expected

QUERY #1
SELECT
dbo.CLIENT.CLIENT_ID, dbo.CLIENT.GOC, dbo.SALES_UW_REGION.SALES_UNDERWRITING
FROM dbo.CLIENT LEFT OUTER JOIN
dbo.SALES_UW_REGION ON dbo.CLIENT.GOC = dbo.SALES_UW_REGION.GOC
WHERE (dbo.CLIENT.CLIENT_ID = 23721)
CLIENT_ID, GOC, SALES_UNDERWRITING
23721 332 Underwriting
23721 332 Sales
I can understand why this would return only one row, the reason being that despite the LEFT outer join which ensures both CLIENT records are returned even if they are unmatched, the FILTER is applied AFTER the join, so the resultset only has one row.
Query #2
SELECT
dbo.CLIENT.CLIENT_ID, dbo.CLIENT.GOC, dbo.SALES_UW_REGION.SALES_UNDERWRITING
FROM dbo.CLIENT LEFT OUTER JOIN
dbo.SALES_UW_REGION ON dbo.CLIENT.GOC = dbo.SALES_UW_REGION.GOC
WHERE (dbo.CLIENT.CLIENT_ID = 23721)
and SALES_UW_REGION.SALES_UNDERWRITING = 'Sales '
CLIENT_ID GOC SALES_UNDERWRITING
23721 332 Sales
However, if I move the 'SALES' filter to the JOIN clause, I was susprised to see that still one row is returned.
Query #3
SELECT
dbo.CLIENT.CLIENT_ID, dbo.CLIENT.GOC, dbo.SALES_UW_REGION.SALES_UNDERWRITING
FROM dbo.CLIENT LEFT OUTER JOIN
dbo.SALES_UW_REGION ON dbo.CLIENT.GOC = dbo.SALES_UW_REGION.GOC
and SALES_UW_REGION.SALES_UNDERWRITING = 'Sales '
WHERE (dbo.CLIENT.CLIENT_ID = 23721)
CLIENT_ID GOC SALES_UNDERWRITING
23721 332 Sales
I expected that since it was part of the JOIN clause and the join was a LEFT OUTER, that I would have gotten 2 rows. In general, if the JOIN condition which involves an equality match on two columns, one from the LEFT table and one from teh RIGHT table is not met, in a LEFT OUTER JOIN the LEFT table would be returned with NULL values for values selected from the RIGHT. Why should it be any different if we are matching a value from the RIGHT table to a literal? Shouldn't the row from teh LEFT table still be returned?
Man, I thought this was basic stuff that I had down....
Here's what you need to recreate what I did:
CREATE TABLE [dbo].[CLIENT](
[CLIENT_ID] [bigint] NOT NULL,
[GOC] [char](3) NULL
)
go
CREATE TABLE [dbo].[SALES_UW_REGION](
[GOC] [char](3) NOT NULL,
[SALES_UNDERWRITING] [varchar](12) NULL
)
go
INSERT INTO [dbo].[CLIENT]([CLIENT_ID], [GOC])
SELECT 23721, N'332'
go
INSERT INTO [dbo].[SALES_UW_REGION]([GOC], [SALES_UNDERWRITING])
SELECT N'332', N'Underwriting' UNION ALL
SELECT N'332', N'Sales'
go
You have one row in your CLIENT table for CLIENT_ID = 23721.
You're left joining the other table which has multiple rows for CLIENT_ID = 23721 (when joined with criteria in your first query), but when the joining criteria is altered it excludes one of those rows from the RIGHT table.
You're getting all records from your LEFT table regardless of whether they join to records in the RIGHT table, just as expected.
I think your confusion involves a misunderstanding of the first result set:
CLIENT_ID, GOC, SALES_UNDERWRITING
23721 332 Underwriting
23721 332 Sales
Though there are two rows in this result set, the results represent data from only one row in the Client table. The join condition allowed the single row from the Client table to match two rows in the Sales_UW_Region table, and so the data for that row from the Client table is duplicated in the result set. There is only one Client record here in the first place, evidenced by the fact that there is only one Client_ID, but the data for the record is shown twice: once for each matching record in Sales_UW_Region.
Later, when you include the and SALES_UW_REGION.SALES_UNDERWRITING = 'Sales ' condition as part of the join's ON clause, the original single record in the Client table only matches one record from the Sales_UW_Region table. The data for the row no longer needs to be duplicated, and so only one row is returned.
Your understanding is correct. If the filter is within the JOIN's ON clause, it will not remove rows from the first table.
I think you need to look elsewhere for your problem... Do you really mean to have a trailing space in your 'Sales ' constant?
Here's a JSFiddle to test this: http://sqlfiddle.com/#!2/bfe32/3/0

Returning "Null" in sql pulls

I don't really know if any source code will help here... But how come when I run my SQL query with a join that every column after about 70 rows gets returned as "Null". Here is my query:
SELECT
P_DATA.MATERIALID,
T_GROUP_PROPERTIES.PROPERTYGROUPID,
T_GROUP_PROPERTIES.PROPERTYTYPEID,
T_GROUP_PROPERTIES.PROPERTYTYPEDESCRIPTION
FROM
P_DATA
LEFT OUTER JOIN TEMPLATE_GROUP_PROPERTIES
ON (P_DATA.MATERIALID = T_GROUP_PROPERTIES.PROPERTYGROUPID)
OR (P_DATA.MATERIALID = T_GROUP_PROPERTIES.PROPERTYTYPEID)
OR (CAST(P_DATA.MATERIALID AS CHAR(2000)) = T_GROUP_PROPERTIES.PROPERTYTYPEDESCRIPTION)
It's the outer join that's giving you extra NULLs. ALL rows from P_DATA will be represented in the results, even if they have no matching row in TEMPLATE_GROUP_PROPERTIES. The query generates NULLs in the output to represent the lack of matching data in the joined table.
Change LEFT OUTER JOIN to INNER JOIN to get rid of the NULLs

How to get unmatched records using SQL query?

Actually if i am doing INNER JOIN of two tables then i will get all matched records from the two tables.
But i want to get all the unmatched rows only.
Is there any way to do that?
Or Any JOIN available for that?
There is join you can use. You need an OUTER JOIN, and only select rows with a NULL on the join condition.
Another option is to use a sub query with a NOT EXISTS or NOT IN as part of your main WHERE clause.

Compare inner join and outer join SQL statements

What is the difference between an inner join and outer join? What's the precise meaning of these two kinds of joins?
Check out Jeff Atwood's excellent:
A Visual Explanation of SQL Joins
Marc
Wikipedia has a nice long article on the topic [here](http://en.wikipedia.org/wiki/Join_(SQL))
But basically :
Inner joins return results where there are rows that satisfy the where clause in ALL tables
Outer joins return results where there are rows that satisfy the where clause in at least one of the tables
You use INNER JOIN to return all rows from both tables where there is a match. ie. in the resulting table all the rows and columns will have values.
In OUTER JOIN the resulting table may have empty columns. Outer join may be either LEFT or RIGHT
LEFT OUTER JOIN returns all the rows from the first table, even if there are no matches in the second table.
RIGHT OUTER JOIN returns all the rows from the second table, even if there are no matches in the first table.
INNER JOIN returns rows that exist in both tables
OUTER JOIN returns all rows that exist in either table
Inner join only returns a joined row if the record appears in both table.
Outer join depending on direction will show all records from one table, joined to the data from them joined table where a corresponding row exists
Using mathematical Set,
Inner Join is A ^ B;
Outer Join is A - B.
So it is (+) is your A side in the query.
Assume an example schema with customers and order:
INNER JOIN: Retrieves customers with orders only.
LEFT OUTER JOIN: Retrieves all customers with or without orders.
RIGHT OUTER JOIN: Retrieves all orders with or without matching customer records.
For a slightly more detailed infos, see Inner and Outer Join SQL Statements