joining more tables makes me get less data from the query - sql

I have one problem with one SP, when I am joining some specific tables, I am getting less data from the SP then I am getting when they are not included in the SP.
I am not getting any data from them yet, I am just joining them and only that makes the SP to send me less data.
Any idea what the problem can be? Thanks

It sounds like there are no matching rows in the tables you're joining to.
If you change the join to a LEFT OUTER JOIN, you should get the rows you are expecting (but, obviously, check the output to make sure you do!)

Joins usually have a join condition in the "ON" clause. That condition says how to match rows between the tables being joined. If, for a particular row on one side, there is no matching row on the other side, then we need to consider what type of join we're dealing with:
For an INNER JOIN, the row will be discarded.
For a LEFT JOIN, and if the row comes from the "LEFT" table source, then this row will appear, but with NULLs present for all columns from the "RIGHT" table source.
RIGHT JOIN is similar to left join, with the directions swapped over.

regardless if you are asking for data from those tables or not, they have been included as part of the join, and the resultset is going to return rows that meet the criteria you have specified.
You may want to post 2 versions of the SP, one with few tables, then a second with one or more of the joins so that it can be better explained what is happening behind the scenes.

Sounds like you're doing an INNER JOIN. This will only return a record if whatever property you're joining on is in both tables. As an example:
Customers
ID Name
1 Mike
2 Steve
3 Amy
Address
ID Address
1 123 Main
3 456 Oak
If you
SELECT Name, Adddress FROM NAME N
Join Address A ON N.Id = A.Id
Only The records for Mike and Amy will be returned because Steve doesn't have an Address record.

I don't know what kind of join you are doing but it exists three kind of join
INNER JOIN : Retrieves datas that matches on both side
LEFT (OUTER) JOIN : Retrieves datas that only match on the left side, even if right is null
RIGHT (OUTER) JOIN Retrieves datas that only mach on the right side, even if left is null
According to which one you are using, datas can be retrieved or not.
But posting your query will let us tell you what might be the real problem.
Hope I could help,

See this blog post by Jeff Atwood. It explains SQL Joins very well. I think it will answer your question about why certain sets of data may or may not be missing.

Related

Newbie to SQL I have run the the inner join query but result comes up with columns only

I have run this query in adventureworks but the result is run successfully but i only get the columns instead of the data with columns how so?
select
a.BusinessEntityID,b.bonus,b.SalesLastYear
from
[Sales].[SalesPersonQuotaHistory] a
inner join
[Sales].[SalesPerson] b
on
a.SalesQuota = b.SalesQuota
My best guess is that instead of joining the tables on SalesQuota, you should be joining them on something else - An ID field, typically.
I don't have Adventureworks here, but judging from the names of the tables and the columns that you've provided, I would assume that there's a SalesPersonID field of some sort that actually connects a Salesperson's quota history to the Salesperson him/herself.
I would expect that you're looking for something closer to this:
SELECT
a.BusinessEntityID
,b.bonus
,b.SalesLastYear
FROM [Sales].[SalesPersonQuotaHistory] a
INNER JOIN [Sales].[SalesPerson] b
ON a.SalesPersonID = b.SalesPersonID
General Knowledge:
INNER JOIN means "Show me only entries (rows) that have a matching value on both sides of the condition." (i.e. The value in Table A matches the value in Table B).
So ON a.SalesQuota = b.SalesQuota means "Only where the value of SalesQuota in Table A matches the value of SalesQuota in Table B."
I'm not sure what the purpose of this query could be, since it is entirely possible that two salespeople have the same values in both tables, and then you would get duplicate rows (because the values of SalesQuota would match in both cases), or that the values wouldn't match at all, and then you wouldn't get any rows - I suspect that is what's happening to you.
Consider the conditions of what you're trying to join. Are you really trying to join quota amounts, or are you trying to retrieve quota information for specific salespeople? The answer should help guide your JOIN conditions.

Access 2010 - Why does a query produce less results than the base table itself

I have created a query in Access 2010 that maps a number in the right table into the left table. when i run the query i get less results than the total number of records in the left table and i wonder why? it seems that some records are left out. Does somebody have a clue on what i am doing wrong?
edit: i cant post pictures so i´ll draw this here in a simplified way:
-table 1....-........-table 2...-..........-table 3... -
-number 1-.<->.-number 1-.........-xxxxxxxx...-
-xxxxxxxx...-.......-number 2-..<->..-number 2-
Query:
SELECT [2007].[Analyse (Nummer)],
[2007].[Analyse (Name)],
[2007].Faktura, BKPF2007.Referenz,
BSET.St
FROM BSET
INNER JOIN (2007 INNER JOIN BKPF2007 ON [2007].[Faktura] = BKPF2007.[Belegnr])
ON BSET.[Belegnr] = BKPF2007.[Referenz]
GROUP BY [2007].[Analyse (Nummer)],
[2007].[Analyse (Name)],
[2007].Faktura,
BKPF2007.Art,
BKPF2007.Referenz,
BSET.St;
That's one of the functions of JOIN - it does not show records that don't match. There are a few things I can suggest without seeing specifics.
Remove one of the joins, so your query only shows Table 1 and Table 2. Make sure you get the expected results before moving on to joining Table 3
Replace your joins with LEFT JOINS which show all records even if there is no match in the right-hand table. Even if this doesn't give you the solution you're hoping for, it may help you diagnose the problem.
This is the reason for your results being filtered:
INNER JOIN
You will need to make this a LEFT JOIN to keep all results where results do not exist on the right tables(s).

Translating Oracle SQL to Access Jet SQL, Left Join

There must be something I'm missing here. I have this nice, pretty Oracle SQL statement in Toad that gives me back a list of all active personnel with the IDs that I want:
SELECT PERSONNEL.PERSON_ID,
PERSONNEL.NAME_LAST_KEY,
PERSONNEL.NAME_FIRST_KEY,
PA_EID.ALIAS EID,
PA_IDTWO.ALIAS IDTWO,
PA_LIC.ALIAS LICENSENO
FROM PERSONNEL
LEFT JOIN PERSONNEL_ALIAS PA_EID
ON PERSONNEL.PERSON_ID = PA_EID.PERSON_ID
AND PA_EID.PERSONNEL_ALIAS_TYPE_CD = 1086
AND PA_EID.ALIAS_POOL_CD = 3796547
AND PERSONNEL.ACTIVE_IND = 1
LEFT JOIN PERSONNEL_ALIAS PA_IDTWO
ON PERSONNEL.PERSON_ID = PA_IDTWO.PERSON_ID
AND PA_IDTWO.PERSONNEL_ALIAS_TYPE_CD = 3839085
AND PA_IDTWO.ACTIVE_IND = 1
LEFT JOIN PERSONNEL_ALIAS PA_LIC
ON PERSONNEL.PERSON_ID = PA_LIC.PERSON_ID
AND PA_LIC.PERSONNEL_ALIAS_TYPE_CD = 1087
AND PA_LIC.ALIAS_POOL_CD = 683988
AND PA_LIC.ACTIVE_IND = 1
WHERE PERSONNEL.ACTIVE_IND = 1 AND PERSONNEL.PHYSICIAN_IND = 1;
This works very nicely. Where I run into problems is when I put it into Access. I know, I know, Access Sucks. Sometimes one needs to use it, especially if one has multiple database types that they just want to store a few queries in, and especially if one's boss only knows Access. Anyway, I was having trouble with the ANDs inside the FROM, so I moved those to the WHERE, but for some odd reason, Access isn't doing the LEFT JOINs, returning only those personnel with EID, IDTWO, and LICENSENO's. Not everybody has all three of these.
Best shot in Access so far is:
SELECT PERSONNEL.PERSON_ID,
PERSONNEL.NAME_LAST_KEY,
PERSONNEL.NAME_FIRST_KEY,
PA_EID.ALIAS AS EID,
PA_IDTWO.ALIAS AS ID2,
PA_LIC.ALIAS AS LICENSENO
FROM ((PERSONNEL
LEFT JOIN PERSONNEL_ALIAS AS PA_EID ON PERSONNEL.PERSON_ID=PA_EID.PERSON_ID)
LEFT JOIN PERSONNEL_ALIAS AS PA_IDTWO ON PERSONNEL.PERSON_ID=PA_IDTWO.PERSON_ID)
LEFT JOIN PERSONNEL_ALIAS AS PA_LIC ON PERSONNEL.PERSON_ID=PA_LIC.PERSON_ID
WHERE (((PERSONNEL.ACTIVE_IND)=1)
AND ((PERSONNEL.PHYSICIAN_IND)=1)
AND ((PA_EID.PRSNL_ALIAS_TYPE_CD)=1086)
AND ((PA_EID.ALIAS_POOL_CD)=3796547)
AND ((PA_IDTWO.PRSNL_ALIAS_TYPE_CD)=3839085)
AND ((PA_IDTWO.ACTIVE_IND)=1)
AND ((PA_LIC.PRSNL_ALIAS_TYPE_CD)=1087)
AND ((PA_LIC.ALIAS_POOL_CD)=683988)
AND ((PA_LIC.ACTIVE_IND)=1));
I think that part of the problem could be that I'm using the same alias (lookup) table for all three joins. Maybe there's a more efficient way of doing this? Still new to SQL land, so any tips as far as that goes would be great. I feel like these should be equivalent, but the Toad query gives me back many many tens of thousands of imperfect rows, and Access gives me fewer than 500. I need to find everybody so that nobody is left out. It's almost as if the LEFT JOINs aren't working at all in Access.
To understand what you are doing, let's look at simplified version of your query:
SELECT PERSONNEL.PERSON_ID,
PA_EID.ALIAS AS EID
FROM PERSONNEL
LEFT JOIN PERSONNEL_ALIAS AS PA_EID ON PERSONNEL.PERSON_ID=PA_EID.PERSON_ID
WHERE PERSONNEL.ACTIVE_IND=1
AND PERSONNEL.PHYSICIAN_IND=1
AND PA_EID.PRSNL_ALIAS_TYPE_CD=1086
AND PA_EID.ALIAS_POOL_CD=3796547
If the LEFT JOIN finds match, your row might look like this:
Person_ID EID
12345 JDB
If it doesn't find a match, (disregard the WHERE clause for a second), it could look like:
Person_ID EID
12345 NULL
When you add the WHERE clauses above, you are telling it to only find records in the PERSONNEL_ALIAS table that meet the condition, but if no records are found, then the values are considered NULL, so they will never satisfy the WHERE condition and no records will come back...
As Joe Stefanelli said in his comment, adding a WHERE clause to a LEFT JOIN'ed table make it act as an INNER JOIN instead...
Further to #Sparky's answer, to get the equivalent of what you're doing in Oracle, you need to filter rows from the tables on the "outer" side of the joins before you join them. One way to do this might be:
For each table on the "outer" side of a join that you need to filter rows from (that is, the three instances of PERSONNEL_ALIAS), create a query that filters the rows you want. For example, the first query (say, named PA_EID) might look something like this:SELECT PERSONNEL_ALIAS.* FROM PERSONNEL_ALIAS WHERE PERSONNEL_ALIAS.PERSONNEL_ALIAS_TYPE_CD = 1086 AND PERSONNEL_ALIAS.ALIAS_POOL_CD = 3796547
In your "best shot in Access so far" query in the original post: a) replace each instance of PERSONNEL_ALIAS with the corresponding query created in Step 1, and, b) remove the corresponding conditions (on PA_EID, PA_IDTWO, and PA_LIC) from the WHERE clause.

What is the difference between `FROM _ , _` and `FROM _ INNER JOIN _ ON _`

What is the Difference between the two?
SELECT [EmployeeList].[Emp_ID], [EmployeeLevel].[LevelPosition]
FROM [EmployeeList], [EmployeeLevel]
SELECT [EmployeeList].[Emp_ID], [EmployeeLevel].[LevelPosition]
FROM EmployeeList INNER JOIN EmployeeLevel ON
[EmployeeList].[LevelID] = [EmployeeLevel].[LevelID]
regardless of the field names.
The first one is not correlated in any way and will return a cross join / cartesian join with every permutation of rows from the 2 tables. You would need to add a WHERE clause
SELECT [EmployeeList].[Emp_ID], [EmployeeLevel].[LevelPosition]
FROM [EmployeeList], [EmployeeLevel]
WHERE [EmployeeList].[LevelID] = [EmployeeLevel].[LevelID]
Then they would be semantically the same but the above is the old style ANSI syntax and is largely discouraged by everyone except Joe Celko due to being less clear and the possibility of causing inadvertent cartesian Joins (as well as being more work to change if you want to convert to an outer join).
Implicit Cross Join vs. Inner Join
http://explainextended.com/2009/07/16/inner-join-vs-cross-apply/
http://en.wikipedia.org/wiki/Join_(SQL)
First one you're selecting a list of employees ids and a list of level positions. (with no necessarily relationship between them).
On the second one you're doing a join. You're relating the list of employees (given its level) with the employees with the same level (see the ON condition).
The first is a Cartesian Product join which does not care about matching rows between the two tables. It creates a list of every combination of row from table1 combined with every row from table2. Unless there is a specific case requiring it, this kind of query produces way too much data of little meaning.
The second matches rows with equivalent IDs.
First one shows all data from EmployeeList and EmployeeLevel table...
In second query, there are a rlation between EmployeeList and EmployeeLevel by LevelID and INNER JOIN means must match between EmployeeList.LevelID and EmployeeLevel.LevelID...
So second query shows data if match both LevelID....

What are the uses of the different join operations?

What are the uses of the different join operations in SQL? Like I want to know why do we need the different inner and outer joins?
The only type of join you really need is LEFT OUTER JOIN. Every other type of join can be rewritten in terms of one or more left outer joins, and possibly some filtering. So why do we need all the others? Is it just to confuse people? Wouldn't it be simpler if there were only one type of join?
You could also ask: Why have both a <= b and b >= a? Don't these just do the same thing? Can't we just get rid of one of them? It would simplify things!
Sometimes it's easier to swap <= to >= instead of swapping the arguments round. Similarly, a left join and a right join are the same thing just with the operands swapped. But again it's practical to have both options instead of requiring people to write their queries in a specific order.
Another thing you could ask is: In logic why do we have AND, OR, NOT, XOR, NAND, NOR, etc? All these can be rewritten in terms of NANDs! Why not just have NAND? Well it's awkward to write an OR in terms of NANDs, and it's not as obvious what the intention is - if you write OR, people know immediately what you mean. If you write a bunch of NANDs, it is not obvious what you are trying to achieve.
Similarly, if you want to do a FULL OUTER JOIN b you could make a left join and a right join, remove duplicated results, and then union all. But that's a pain and so there's a shorthand for it.
When do you use each one? Here's a simplified rule:
If you always want a result row for each row in the LEFT table, use a LEFT OUTER JOIN.
If you always want a result row for each row in the RIGHT table, use a RIGHT OUTER JOIN.
If you always want a result row for each row in either table, use a FULL OUTER JOIN.
If you only want a result row when there's a row in both tables, use an INNER JOIN.
If you want all possible pairs of rows, one row from each table, use a CROSS JOIN.
inner join - joins rows from both sets of the match based on specified criteria.
outer join - selects all of one set, along with matching or empty (if not matched) elements from the other set. Outer joins can be left or right, to specify which set is returned in its entirety.
To make the other answers clearer - YOU GET DIFFERENT RESULTS according to the join you choose, when the columns you're joining on contain null values - for example.
So - for each Real-life scenario there is a join that suits it (either you want the lines without the data or not in the null values example).
My answer assumes 2 tables joined on a single key:
INNER JOIN - get the results that are in both join tables (according to the join rule)
FULL OUTER JOIN - get all results from both table (Cartesian product)
LEFT OUTER JOIN - get all the results from left table and the matching results from the right
You can add WHERE clauses in order to further constrain the results.
Use these in order to only get what you want to get.