SQL left join gives wrong results - sql

In table A (i.e. Charges) I have my data and in B (i.e gdh) there are mappings.
For some reason my query doesn't show rows without mappings with null value.
Any thoughts?
select a.chargeable_object, a.debitor, a.source_bu, a.target_cc, a.target_bu, b.L5_CLUSTER, sum(a.charge)
from charges a
left join gdh b on a.target_cc = b.department_id
where a.account not like ('H%')
and a.chargeable_object is not null
and a.source_bu in ('301','161','303')
and a.debitor not in ('0315X02', '0961901', '0972023', '0972024',......)
group by a.chargeable_object, a.debitor, a.source_bu, a.target_cc, a.target_bu, b.L5_CLUSTER

It would help to see some example data. Anyhow does the column a.target_cc contains null values? I would expect that those would be filtered out.

Related

Should I use an SQL full outer join for this?

Consider the following tables:
Table A:
DOC_NUM
DOC_TYPE
RELATED_DOC_NUM
NEXT_STATUS
...
Table B:
DOC_NUM
DOC_TYPE
RELATED_DOC_NUM
NEXT_STATUS
...
The DOC_TYPE and NEXT_STATUS columns have different meanings between the two tables, although a NEXT_STATUS = 999 means "closed" in both. Also, under certain conditions, there will be a record in each table, with a reference to a corresponding entry in the other table (i.e. the RELATED_DOC_NUM columns).
I am trying to create a query that will get data from both tables that meet the following conditions:
A.RELATED_DOC_NUM = B.DOC_NUM
A.DOC_TYPE = "ST"
B.DOC_TYPE = "OT"
A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999
A.DOC_TYPE = "ST" represents a transfer order to transfer inventory from one plant to another. B.DOC_TYPE = "OT" represents a corresponding receipt of the transferred inventory at the receiving plant.
We want to get records from either table where there is an ST/OT pair where either or both entries are not closed (i.e. NEXT_STATUS < 999).
I am assuming that I need to use a FULL OUTER join to accomplish this. If this is the wrong assumption, please let me know what I should be doing instead.
UPDATE (11/30/2021):
I believe that #Caius Jard is correct in that this does not need to be an outer join. There should always be an ST/OT pair.
With that I have written my query as follows:
SELECT <columns>
FROM A LEFT JOIN B
ON
A.RELATED_DOC_NUM = B.DOC_NUM
WHERE
A.DOC_TYPE IN ('ST') AND
B.DOC_TYPE IN ('OT') AND
(A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999)
Does this make sense?
UPDATE 2 (11/30/2021):
The reality is that these are DB2 database tables being used by the JD Edwards ERP application. The only way I know of to see the table definitions is by using the web site http://www.jdetables.com/, entering the table ID and hitting return to run the search. It comes back with a ton of information about the table and its columns.
Table A is really F4211 and table B is really F4311.
Right now, I've simplified the query to keep it simple and keep variables to a minimum. This is what I have currently:
SELECT CAST(F4211.SDDOCO AS VARCHAR(8)) AS SO_NUM,
F4211.SDRORN AS RELATED_PO,
F4211.SDDCTO AS SO_DOC_TYPE,
F4211.SDNXTR AS SO_NEXT_STATUS,
CAST(F4311.PDDOCO AS VARCHAR(8)) AS PO_NUM,
F4311.PDRORN AS RELATED_SO,
F4311.PDDCTO AS PO_DOC_TYPE,
F4311.PDNXTR AS PO_NEXT_STATUS
FROM PROD2DTA.F4211 AS F4211
INNER JOIN PROD2DTA.F4311 AS F4311
ON F4211.SDRORN = CAST(F4311.PDDOCO AS VARCHAR(8))
WHERE F4211.SDDCTO IN ( 'ST' )
AND F4311.PDDCTO IN ( 'OT' )
The other part of the story is that I'm using a reporting package that allows you to define "virtual" views of the data. Virtual views allow the report developer to specify the SQL to use. This is the application where I am using the SQL. When I set up the SQL, there is a validation step that must be performed. It will return a limited set of results if the SQL is validated.
When I enter the query above and validate it, it says that there are no results, which makes no sense. I'm guessing the data casting is causing the issue, but not sure.
UPDATE 3 (11/30/2021):
One more twist to the story. The related doc number is not only defined as a string value, but it contains leading zeros. This is true in both tables. The main doc number (in both tables) is defined as a numeric value and therefore has no leading zeros. I have no idea why those who developed JDE would have done this, but that is what is there.
So, there are matching records between the two tables that meet the criteria, but I think I'm getting no results because when I convert the numeric to a string, it does not match, because one value is, say "12345", while the other is "00012345".
Can I pad the numeric -> string value with zeros before doing the equals check?
UPDATE 4 (12/2/2021):
Was able to finally get the query to work by converting the numeric doc num to a left zero padded string.
SELECT <columns>
FROM PROD2DTA.F4211 AS F4211
INNER JOIN PROD2DTA.F4311 AS F4311
ON F4211.SDRORN = RIGHT(CONCAT('00000000', CAST(F4311.PDDOCO AS VARCHAR(8))), 8)
WHERE F4211.SDDCTO IN ( 'ST' )
AND F4311.PDDCTO IN ( 'OT' )
AND ( F4211.SDNXTR < 999
OR F4311.PDNXTR < 999 )
You should write your query as follows:
SELECT <columns>
FROM A INNER JOIN B
ON
A.RELATED_DOC_NUM = B.DOC_NUM
WHERE
A.DOC_TYPE IN ('ST') AND
B.DOC_TYPE IN ('OT') AND
(A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999)
LEFT join is a type of OUTER join; LEFT JOIN is typically a contraction of LEFT OUTER JOIN). OUTER means "one side might have nulls in every column because there was no match". Most critically, the code as posted in the question (with a LEFT JOIN, but then has WHERE some_column_from_the_right_table = some_value) runs as an INNER join, because any NULLs inserted by the LEFT OUTER process, are then quashed by the WHERE clause
See Update 4 for details of how I resolved the "data conversion or mapping" error.

MS Access SQL left join giving all 0

I am trying to make a summary table of all the items I have. I have a raw data table with 10 users who respectively have different items. There are maximum 3 different items and I want to do a count to see how many items each individual has. The following is my code.
Select b.Country,b.UserID,Num_including_fruits, Apple,Orange
from
(((SELECT o.Country,o.UserID, IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID))
AS Num_including_fruits
FROM [SEA2_View] as o
GROUP BY o.UserID, o.Country
ORDER BY Country)as b
LEFT JOIN
(SELECT o.Country,o.UserID,IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID)
AS Apple
FROM [APAC2_View] as o
WHERE o.fruit_status <>"fresh" AND o.HWType = "Apple"
GROUP BY o.Country,o.UserID)as d
ON (b.UserID = d.UserID))
LEFT JOIN
(SELECT o.Country,o.UserID,IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID))
AS Orange
FROM [SEA2_View] as o
WHERE o.fruit_status <>"fresh" AND o.HWType = "Orange"
GROUP BY o.Country,o.UserID)as e
ON (d.UserID = e.UserID))
;
The first join returns the correct result but the second join somehow returns all 0, which is incorrect. Therefore please help! and I would appreciate any advice for best practice when it comes to joins in SQL. Thanks lot!
Are you sure you don't have a table naming error?
You're first joining [SEA2_View] with [APAC2_View]. The second join is joining with [SEA2_View] with itself.

left join excludes nulls and takes left value

SELECT p.ticket AS posted,
e.ticket AS settled,
Sum(e.amount)
FROM post AS p
LEFT JOIN settle AS e
ON p.ticket = e.ticket
WHERE p.date = '2016-05-10 00:00:00.000'
GROUP BY p.pticket,
e.eticket
ORDER BY posted
I understand that the grouping or where is the culprit but I've tried so many variations, the rows for the two tables are :
(Table1=Table2)
(total = (item + tax= total))
So the second table has 2 rows that I sum. I need the date because it has to much info and I've tried "is null" in dates and in other places but can't get this right. Instead of null, it shows the value of the left table as if they match.
So I figured out! Just love this site and wanted to leave input for whoever runs into this, please correct me if my information is not accurate as I would like to explain in detail but basically, from what I understand and from SQL Fundamentals, nulls are considered outer rows and therefore I would need a "Left Outer Join":
SELECT p.ticket AS posted,
e.ticket AS settled,
Sum(e.amount)
FROM post AS p
LEFT JOIN settle AS e
ON p.ticket = e.ticket
WHERE p.date = '2016-05-10 00:00:00.000'
GROUP BY p.pticket,
e.eticket
ORDER BY posted
A good rule that stood out for me and helps me check my joins with nulls is that the Where clause should only have conditions to the table where the nulls will not be included, so you keep the outer rows, with the exception of "is null". You could use that with a column on the non-preserved table and still get nulls.

Joining Tables: Only (!) add missing rows

I want to join the following tables (records, tip). Goal is that the missing WAR rows (dependend on the ID) will be added. For example you see that WAR = 2 is missing for ID = 80.
Note: WAR is always smaller or equal with the value of TIP. The value of Value should be NULL in the added rows. The table in the bottom is the goal.
I am not sure how to solve this problem. But a condition that results of this is records."TIP" >= tip."TIP".
I use HANA as database.
Thank you in advance. Best regards.
This is how it works (sorry all these TIPs are a little bit confusing):
SELECT a."ID", b."TiP" "WAR", c."VAL" FROM (
SELECT DISTINCT "ID", MAX("TIP") "max" FROM records t
GROUP BY "ID"
) a
INNER JOIN tip b ON 1=1
LEFT JOIN T0 c ON a."ID" = c."ID" AND b."TiP" = c."WAR"
WHERE b."TiP" <= a."max"
ORDER BY a."ID", b."TiP"

SQL using inner join

So this is the situation I have. I have 3 tables (tblEmployeesinfo , sqlSumrepMTC, sqlSumrepMTC15th) I display this info using inner join:
SELECT
SQLSummRepMTC."RepCompany", SQLSummRepMTC."WHTax",
SQLSummRepMTC."Company", SQLSummRepMTC."MonthName",
SQLSummRepMTC."YearVal", SQLSummRepMTC."Basis",
tblEmployeesInfo."LastName", tblEmployeesInfo."FirstName",
tblEmployeesInfo."Company", tblEmployeesInfo."MInitial",
tblEmployeesInfo."Division", sqlSumrepMTC15th."WHTax",
sqlSumrepMTC15th."Basis"
FROM
{
oj ("BIOMETRICS"."dbo"."SQLSummRepMTC" SQLSummRepMTC INNER JOIN
"BIOMETRICS"."dbo"."tblEmployeesInfo" tblEmployeesInfo
ON SQLSummRepMTC."EmployeeNo" = tblEmployeesInfo."EmployeeNo")
INNER JOIN "BIOMETRICS"."dbo"."sqlSumrepMTC15th" sqlSumrepMTC15th
ON tblEmployeesInfo."EmployeeNo" = sqlSumrepMTC15th."EmployeeNo"
}
ORDER BY
SQLSummRepMTC."Basis" ASC,
tblEmployeesInfo."Company" ASC,
tblEmployeesInfo."LastName" ASC
Let's say one employee has his record on sqlSumrepMTC with its field Taxvalue of 50 but he does not exist on sqlSumrepMTC15th my problem is that this record will not be displayed in the inner join since it does not have value on both tables. What i want to achieve is just display a 0 value when it does not exist in the other table. This is my report looks like.
Employeeno employeename 15th 30th
01 james 10 20
02 Chris NULL 50
first record will appear in the report since it has both record existing in the two tables, the second will not since its null in the first table. I just need it to appear in the report if one value is null or is missing from the other. Thanks in advance
You have two joins! Thus, if there is no record in sqlSumrepMTC15th you need to replace the second join with LEFT JOIN. If it is possible, that there is no join record in sqlSumrepMTC15th AND tblEmployeesInfo, you need to replace both joins with LEFT JOIN.
Furthermore, you can replace NULL by
SELECT CASE
WHEN attribute IS NULL
THEN 0
ELSE attribute
END AS resultColumName,
nextAttribute
FROM ...