record doesn't show up if there's no corresponding data - sql

I have a few tables I'm trying to join however, I'm missing some rows if there's no data, but would like to have them be displayed
tblCountry
sID sCountry
1 Algeria
2 Armenia
3 Belgium
tblRefData
RefID IDnum sID
1 7 1
2 8 2
3 9 3
tblMData
IDnum IDa
7 123
8 123
Here's what my query looks like:
Select tblCountry.sCountry, count(tblMData.Ida) as CountIDa
From tblRefData
inner join tblMData on tblRefData.IDnum = tblMData.IDnum
inner join tblCountry on tblRefData.sID = tblCountry.sID
GroupBy tblCountry.sCountry
What my desired end result is:
sCountry CountIDa
Algeria 1
Armenia 1
Belgium 0
What I'm currently getting is
sCountry CountIDa
Algeria 1
Armenia 1
So if country does not have corresponding data in tblMData, that country does not show up in my result. Any ideas?

You should use left join if the on condition columns values don't match
Select
tblCountry.sCountry,
case
when (count(tblMData.Ida) is null) then 0 end as CountIDa
From
tblRefData
left join
tblMData on tblRefData.IDnum = tblMData.IDnum
left join
tblCountry on tblRefData.sID = tblCountry.sID
Group By
tblCountry.sCountry

You could change the 'INNER JOIN' to a 'LEFT JOIN' to bring back data when there is no corresponding data. Then you could you the ISNULL() function to set the NULL value to a zero.

You want a left join, but have to rearrange the from clause:
Select c.sCountry, count(m.Ida) as CountIDa
From tblCountry c left join
tblRefData r
on r.sID = c.sID left join
tblMData m
on r.IDnum = m.IDnum
GroupBy c.sCountry;
Notice that the table aliases make the query easier to write and to read.

Related

SELECT from 2 differents tables

I would like to select all possible brands for different products where the fk_category_id is for example equal to "2".
produits :
id titre fk_category_id fk_marque_id is_active is_delete
1 Swoke 2 1 1 0
2 Café 2 2 1 0
3 Fraise 2 3 1 0
4 Fruits 2 4 1 0
manufacturers :
id name
1 Swoke
2 Liqua
3 Alfaliquid
4 TJuice
5 otherBrands
I already tried a lot of things and for example this request :
SELECT m.name, m.id, p.fk_category_id
FROM produits p
INNER JOIN manufacturers m
WHERE p.fk_category_id = 2
AND p.is_active = 1
AND p.fk_marque_id = m.id
AND p.is_delete = 0;
But it doesn't works.
The expected result is :
result :
id name
1 Swoke
2 Liqua
3 Alfaliquid
4 TJuice
It's the same as the table "manufacturers" but I have to sort by fk_category_id because I only want the brand with the fk_category = 2.
So if someone could explain me or help me to understand how to solve my "problem" ? Thanks you in advance, I continue my research by my side :).
If you need something else i can give you anything.
I think what you need to do is have a condition on your join, to say how the data from the 2 table should join together.
On the assumption that fk_marque_id is your reference in produits to an item in manufacturers (assumed from looking at your where clause), your sql could look like this:
SELECT
p.id, p.titre, m.name, m.id, p.fk_category_id
FROM
produits p
INNER JOIN manufacturers m ON p.fk_marque_id = m.id
WHERE p.fk_category_id = 2
AND p.is_active = 1
AND p.is_delete = 0;
The naming convention of your fields in produits is a little weird however, if one of the the FK fields is a link to an ID in manufacturers. You'd normally expect to see something like FK_manufacturers_Id so it's clear that this column is the reference to that field (Id) in that table (manufacturers)
If you are just looking to join products and manufacturers table where fk_category_id = 2, it can be done something like this
SELECT m.id, m.name
FROM manufacturers m
INNER JOIN produits p
ON m.id = p.fk_marque_id
WHERE p.fk_category_id = 2
AND p.is_active = 1
AND p.is_delete = 0;

What is outer apply in SQL?

select *
from Kosten_Test a
left join T_Pflege_Parameter pv on pv.Parameterbezeichnung = 'Dummy' and pv.Parametereigenschaft = 'Dummy3'
left join T_Pflege_Parameter pp on pp.Parameterbezeichnung = 'Dummy2' and pp.Parametereigenschaft = a.Herkunft
outer apply( select max(VarianteID) as VarianteID, MerkmalTyp, MerkmalWert
from Test2
where MerkmalTyp = pv.Parameterwert and MerkmalWert = sku
group by MerkmalWert, MerkmalTyp
union
select max(VarianteID) as VarianteID, MerkmalTyp, MerkmalWert
from Testvariante_ASIN_SKU
where MerkmalTyp = pv.Parameterwert and MerkmalWert = a.asin
group by MerkmalWert, MerkmalTyp
) vm
left join (select distinct bundleid from T_Archiv_BundleKomponente) bk on bk.BundleID = vm.VarianteID
Because of the Outer Apply Statement i become always double results. Who can help?
Outer apply is not like a LEFT JOIN. It will apply all the values from the OUTER APPLY Statement to the data joined against.
If your query without the outer apply returns 5 rows and the outer apply query returns 5 rows then the resulting dataset would contain 25 records with each record from the outer apply joined to each row of the other data.
Often times data would be condensed down using aggregations of the values returned from the outer apply query grouped inside of the main query.
Example -
Q1
----
A
B
C
OuterApplyQuery
-----------------
1
2
3
SELECT * FROM Q1 OUTER APPLY (SELECT * FROM OuterApplyQuery) AS X
Result
---------
A 1
A 2
A 3
B 1
B 2
B 3
C 1
C 2
C 3

LEFT OUTER JOIN not always matching

I'm starting with a SQL query with a couple of joins and I'm getting the exact data I expect. This is what the current query is.
SELECT DISTINCT o.OrganizationHierarchyUnitLevelFourCd, o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm
FROM Lab_Space l
JOIN Worker w ON l.Contact_WWID = w.WWID AND w.Employee_Status_Code = 'A'
JOIN Org_Hierarchy o ON o.OrganizationHierarchyUnitLevelThreeNm IS NOT NULL AND w.Org_Hierarchy_Unit_Cd = o.OrganizationHierarchyUnitCd
ORDER BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm
This ends up with a row like
1234 | Finance | IT
Now I've created a new table, where I'm tracking whether or not I want to include the organization in my output. That table just has two columns, an org ID and a bit field. So I thought I could LEFT OUTER JOIN, since the second table won't have data on all orgs, so I expanded the query to this:
SELECT DISTINCT o.OrganizationHierarchyUnitLevelFourCd, o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, v.Include
FROM Lab_Space l
JOIN Worker w ON l.Contact_WWID = w.WWID AND w.Employee_Status_Code = 'A'
JOIN Org_Hierarchy o ON o.OrganizationHierarchyUnitLevelThreeNm IS NOT NULL AND w.Org_Hierarchy_Unit_Cd = o.OrganizationHierarchyUnitCd
LEFT OUTER JOIN Validation_Email_Org_Unit_Inclusion v ON o.OrganizationHierarchyUnitCd = v.OrganizationHierarchyUnitCd
ORDER BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm
The problem I have is now I end up with rows like so:
1234 | Finance | IT | NULL
1234 | Finance | IT | 1
Since the Validation_Email_Org_Unit_Inclusion table includes a 1 for the 1234 org, I would expect to just get a single row with a value of 1, not include the row with NULL.
What have I done wrong?
You output OrganizationHierarchyUnitLevelFourCd but currently join on OrganizationHierarchyUnitCd. Join on the same column you output to get the corresponding value.
SELECT DISTINCT o.OrganizationHierarchyUnitLevelFourCd, ...
...
LEFT OUTER JOIN Validation_Email_Org_Unit_Inclusion v ON o.OrganizationHierarchyUnitLevelFourCd = v.OrganizationHierarchyUnitCd
...

SQL Access 2003 create column if exisit value

I've three table
Product
- ID_Product
UP
- ID_Product
- UP_SUM
DOWN
- ID_Product
- DOWN_SUM
The query on this three tables create a column Total_SUM = [UP_SUM]-[DOWN_SUM]
The problem is that if there is no value in DOWN_SUM there is no result in Total_SUM.
EX.
UP
1 - 2
2 - 4
3 - 2
DOWN
1 - 1
3 - 1
TOTAL_SUM
(1) 1
(2) 4 -> value missing
(3) 1
In the fact i don't get the value for the ID 2.
How can i use statement if not isNULL to get all values in TOTAL_SUM? Actually the SQL Query is:
SELECT
Product.ID_Product,
UP.UP_SUM,
DOWN.DOWN_SUM,
[UP_SUM]-[DOWN_SUM] AS TOTAL_SUM,
FROM (PRODUCT INNER JOIN UP ON Product.ID_Product = UP.ID_Product)
INNER JOIN DOWN ON Product.ID_Product = DOWN.ID_Product;
use the iif condition that will replace null with a value, and use left outer join since normal join is filtering those rows without a match. A left join will keep them with the values NULL
IIF(ISNULL(DOWN.DOWN_SUM),0,DOWN.DOWN_SUM)
SELECT
Product.ID_Product,
IIF(ISNULL(UP.UP_SUM),0,UP.UP_SUM),
IIF(ISNULL(DOWN.DOWN_SUM),0,DOWN.DOWN_SUM),
IIF(ISNULL(UP.UP_SUM),0,UP.UP_SUM)-IIF(ISNULL(DOWN.DOWN_SUM),0,DOWN.DOWN_SUM) AS TOTAL_SUM,
FROM (PRODUCT LEFT OUTER JOIN UP ON Product.ID_Product = UP.ID_Product)
LEFT OUTER JOIN DOWN ON Product.ID_Product = DOWN.ID_Product;

Optional filter on a left join column

I'm having issues wrapping my head around how to write a procedure that includes an optional filter on a left join.
I have two tables, Issues, and Customer_Location. Not all issues have been linked to a customer location. So I am fine with this as a starting point:
SELECT
I.Issue_Number,
C.Customer_Location_Code
FROM Issues I
LEFT JOIN Customer_Location C
ON C.Customer_Location_Key = I.Customer_Location_Key
Issue_Number | Customer_Location_Code
1 | Chicago
2 | NULL
3 | Chicago
4 | New York
And this works, it gives me all the issues. But I want to add an optional parameter for the customer location code that if left null would return all 4 issues, but if set to say 1 for Chicago, only issue 1 and 3 would return.
I've tried this
DECLARE #customer_location_key INT
SET #customer_location_key = 1
SELECT
I.Issue_Number,
C.Customer_Location_Code
FROM Issues I
LEFT JOIN Customer_Location C
ON C.Customer_Location_Key = I.Customer_Location_Key
AND C.Customer_Location_Key = #customer_location_key
But I get the following results
Issue_Number | Customer_Location_Code
1 | Chicago
2 | NULL
3 | Chicago
4 | NULL
For some reason I seem to be having a brain fart right now and just can't seem to get my head around what SHOULD be something rather simple
Adding a where clause similar to below should do it.
DECLARE #customer_location_key INT
SET #customer_location_key = 1
SELECT
I.Issue_Number,
C.Customer_Location_Code
FROM Issues I
LEFT JOIN Customer_Location C
ON C.Customer_Location_Key = I.Customer_Location_Key
where (#customer_location_key is null or C.Customer_Location_Key = #customer_location_key)
Use the where clause instead
DECLARE #customer_location_key INT
SET #customer_location_key = 1
SELECT
I.Issue_Number,
C.Customer_Location_Code
FROM Issues I
LEFT JOIN Customer_Location C
ON C.Customer_Location_Key = I.Customer_Location_Key
WHERE
(#customer_location_key is null OR C.Customer_Location_Key = #customer_location_key)
The reason that your query does not work as you expect is that first the 2 ON conditions are examined and then, because of the LEFT JOIN, all rows of table Issue that haven't been matched are added as well (with NULLs in the columns of table Customer_Location_Code).
DECLARE #customer_location_key INT
SET #customer_location_key = 1
SELECT
I.Issue_Number,
C.Customer_Location_Code
FROM Issues I
LEFT JOIN Customer_Location C
ON C.Customer_Location_Key = I.Customer_Location_Key
WHERE ( #customer_location_key IS NULL )
OR ( C.Customer_Location_Key = #customer_location_key )