Left outer join with 2 column missing some output rows - sql

When I select all rows from table zvw_test it return 145 rows.
Table Customer_Class_Price have 160 rows.
When I try to join this 2 table with 2 condition it return 122 rows.
I don't understand why it not return all rows from zvw_test (145 rows)
becasue I use left outer join it should return all rows from left table.
Thank you.
SELECT zvw_test.Goods_ID,
zvw_test.Thai_Name,
zvw_test.UM,
zvw_test.CBal,
Customer_Class_Price.ListPrice
FROM zvw_test
LEFT OUTER JOIN
Customer_Class_Price ON zvw_test.Goods_ID = Customer_Class_Price.Goods_ID AND
zvw_test.UM = Customer_Class_Price.UM
WHERE (Customer_Class_Price.ClassCode = '444-666')

By putting one of your columns from the LEFT OUTER JOIN table in your WHERE clause, you have effectively turned it into an INNER JOIN. You need to move that up to the JOIN clause.

I had this problem before, I used a CTE to solve this, like:
WITH A AS
(
SELECT Customer_Class_Price.Goods_ID, Customer_Class_Price.UM, Customer_Class_Price.ListPrice
FROM Customer_Class_Price
WHERE Customer_Class_Price.ClassCode = '444-666'
)
SELECT zvw_test.Goods_ID, zvw_test.Thai_Name, zvw_test.UM, zvw_test.CBal, A.ListPrice
FROM zvw_test LEFT OUTER JOIN A
ON zvw_test.Goods_ID = A.Goods_ID AND zvw_test.UM = A.UM

You demand in your WHERE clause:
(Customer_Class_Price.ClassCode = '444-666')
Ergo you are not selecting rows where Customer_Class_Price.ClassCode IS NULL. Customer_Class_Price.ClassCode would be NULL if there is no corresponding row, but you are filtering those out explicitely.

Related

Hive non-equi Join on OR condition

I have two tables I want to join on 3 keys. However, one of the keys may contain a value that doesn't exist in the other table, but I still want to retain these records upon query.
Something similar to this where key_3 in the first_table may contain a value of 0 which does not exist in the second_table.
SELECT
f.key_1,
f.key_2,
f.key_3,
s.column_4
FROM
first_table f
LEFT OUTER JOIN second_table s
ON f.key_1 = s.key_1
AND f.key_2 = s.key_2
AND (f.key_3 = s.key_3 OR f.key_3 = 0)
When I run this I get an error of OR not supported in JOIN currently '0'. I know in newer versions of Hive this is allowed, but is there a workaround for it in older versions.
Move condition with OR to the WHERE clause:
SELECT
f.key_1,
f.key_2,
f.key_3,
s.column_4
FROM
first_table f
LEFT OUTER JOIN second_table s
ON f.key_1 = s.key_1
AND f.key_2 = s.key_2
WHERE f.key_3 = s.key_3
OR f.key_3 = 0
OR s.key_1 is NULL --allow not joined records
I may not fully understand your question, but doesn't a simple left join do what you want?
SELECT f.key_1, f.key_2, f.key_3, s.column_4
FROM first_table f LEFT OUTER JOIN
second_table s
ON f.key_1 = s.key_1 AND
f.key_2 = s.key_2 AND
f.key_3 = s.key_3 ;
If there is no match in the second table -- regardless of the values in the first table -- the rows from the first table are still returned.

Postgresql - Conditional Join if data exist

My current query show the data from the table called "Buque" and has some references from another tables. The problem is when i execute the query it never shows the result because it consumes too much memory i guess.
The current query i have
select buq.buq_codigo, tbu.tbu_codigo, tbu.tbu_nombre, pai.pai_codigo, pai.pai_nombre,
pue.pto_codigo, pue.pto_nombre, lin.lin_codigo, lin.lin_nombre, tra.tra_codigo,
tra.tra_nombre, buq.buq_nombre, buq.buq_des, buq.num_trb, buq.num_eslora,
buq.max_tons, buq.reg_lloyd, buq.buq_codigo1, buq.codigo_omi,
case buq.buq_estado when 'A' then 'Activo' else 'Inactivo' end as buq_estado
from publico.mae_buque as buq, publico.mae_tipbuque as tbu, publico.mae_pais as pai,
publico.mae_puerto as pue, publico.mae_linea as lin, publico.mae_trafico as tra
where buq.tbu_codigo = tbu.tbu_codigo or
buq.pai_codigo = pai.pai_codigo or
buq.pto_codigo = pue.pto_codigo or
buq.lin_codigo = lin.lin_codigo or
buq.tra_codigo = tra.tra_codigo
I also tried with inner joins but the problem is it returns me the data that meets the conditions of the joins. In other words, if the join has data to compare, returns the name, if not, show the null data.
The query must return me 611 records, with inner joins returns 68 records.
Concerning your desired result, use left outer joins, which fill up any non-existing rows of the right hand side table with null-values;
Concerning the out of memory issue, note that you used or to connect your tables; this actually leads to the fact that almost every record of the involved tables is connected to almost every other record (almost a cross join / cartesian product); This can get very large if you connect 6 tables...
select buq.buq_codigo, tbu.tbu_codigo, tbu.tbu_nombre, pai.pai_codigo, pai.pai_nombre,
pue.pto_codigo, pue.pto_nombre, lin.lin_codigo, lin.lin_nombre, tra.tra_codigo,
tra.tra_nombre, buq.buq_nombre, buq.buq_des, buq.num_trb, buq.num_eslora,
buq.max_tons, buq.reg_lloyd, buq.buq_codigo1, buq.codigo_omi,
case buq.buq_estado when 'A' then 'Activo' else 'Inactivo' end as buq_estado
from publico.mae_buque as buq
left outer join publico.mae_tipbuque as tbu on buq.tbu_codigo = tbu.tbu_codigo
left outer join publico.mae_pais as pai on (buq.pai_codigo = pai.pai_codigo)
left outer join publico.mae_puerto as pue on (buq.pto_codigo = pue.pto_codigo)
left outer join publico.mae_linea as lin on (buq.lin_codigo = lin.lin_codigo)
left outer join publico.mae_trafico as tra on (buq.tra_codigo = tra.tra_codigo)
You have to use left outer join:
select *
from
publico.mae_buque as buq
left outer join publico.mae_tipbuque as tbu on (buq.tbu_codigo = tbu.tbu_codigo)
left outer join publico.mae_pais as pai on (buq.pai_codigo = pai.pai_codigo)
left outer join publico.mae_puerto as pue on (buq.pto_codigo = pue.pto_codigo )
left outer join publico.mae_linea as lin on (buq.lin_codigo = lin.lin_codigo)
left outer join publico.mae_trafico as tra on (buq.tra_codigo = tra.tra_codigo);

Return blank data if the column is empty in SQL

I have run the following query which returns 36 rows of data
SELECT
A.OBJECTIVE, SUM(A.T_VALUE)
FROM
DB2ADM2.TFINTR10 A
WHERE
(A."YEAR" =10)
AND (A.OBJECTIVE BETWEEN 'WAAAA' AND 'WZZZZ')
GROUP BY
A.OBJECTIVE
When I merge with another table and add the Narration field (OB_Narr5) the rows of data are reduced as the Ob_Narr5 does not exist for every Objective, see sql.
SELECT A.OBJECTIVE, SUM ( A.T_VALUE ), B.OB_NARR5
FROM DB2ADM2.TFINTR10 A INNER JOIN DB2ADM2.TFINOBJP B ON B.OB_12345 = A.
OBJECTIVE
WHERE (A."YEAR" =10)
AND A.OBJECTIVE BETWEEN 'WAAAA' AND 'WZZZZ'
GROUP BY A.OBJECTIVE, B.OB_NARR5
The rows returned are now only 4.
How can I return all the rows including the blank fields and / or return just the rows with the blank fields?
Thanks for replies, Left and Full Outer Join both work.
How do I replace the <NULL> with a blank instead please?
WAAAA -173597.12 <NULL>
WABAA 222717.76 GENERAL
Use LEFT JOIN instead of INNER JOIN which doesnt drop entries of the left table containing empty columns
You can use Full Outer Join for preserving values from both the tables
or Left Outer Join for any particular table
select A.OBJECTIVE
,SUM(A.T_VALUE)
,B.OB_NARR5
from DB2ADM2.TFINTR10 A
left join DB2ADM2.TFINOBJP B on B.OB_12345 = A.OBJECTIVE
where A."YEAR" = 10
and A.OBJECTIVE between 'WAAAA' and 'WZZZZ'
group by A.OBJECTIVE
,B.OB_NARR5

SQL Server 2008R2 Full outer join not working

I am trying to run the below query
SELECT mr.AsofDate as date,
mr.FA,
mr.TPNL as tpnl,
mr.MPNL as mpnl,
mrf.tpnl as mrfTpnl,
mrf.cpnl as mrfCpnl
FROM vw_daily mr
FULL OUTER JOIN mrfeeddaily mrf
ON mr.FA = mrf.book and mr.AsofDate = mrf.AsOfDate
WHERE mr.AsofDate = '20141121'
But i end up getting only rows from the first View vw_daily and the columns from mrfeeddaily are NULL, doesn't Full join return all non matching rows as well ? what am i missing.
There is no common data between the view and the table.
Move the filter to ON condition
ON tells what are the rows to used for Joining but where clause filters the result of join.
Only matched rows in vw_daily table is going to have value in asofdate so the filtering the rows in Where clause is going to do implicit conversion from FULL OUTER JOIN to INNER JOIN
SELECT mr.asofdate AS date,
mr.fa,
mr.tpnl AS tpnl,
mr.mpnl AS mpnl,
mrf.tpnl AS mrfTpnl,
mrf.cpnl AS mrfCpnl
FROM vw_daily mr
FULL OUTER JOIN mrfeeddaily mrf
ON mr.fa = mrf.book
AND mr.asofdate = mrf.asofdate
AND mr.asofdate = '20141121'
Filter the condition in your join.
SELECT mr.AsofDate AS date, mr.FA, mr.TPNL AS tpnl, mr.MPNL AS mpnl, mrf.tpnl AS mrfTpnl, mrf.cpnl AS mrfCpnl
FROM vw_daily mr
FULL OUTER JOIN mrfeeddaily mrf ON mr.FA = mrf.book
AND mr.AsofDate = mrf.AsOfDate
AND mr.AsofDate = '20141121'

Why does my SELECT return only a subset of the rows?

I'm working with an Oracle database for the first time and stumbled upon another problem again. When I want to select all the rows in a table with some JOINS I only get the first 350 rows of about 15.000 rows.
Anyone know if there is a set limit somewhere I'm not aware of?
Below is my query if needed:
SELECT orders.plant, orders.workcenter, workcenters.occupied,
workcenters.section, workcentersections.section, orders.capacitycat,
orders.week, orders.earlieststartdate, orders.lateststartdate,
orders.useropstatus, orders.programstatus, orders.reqhours,
orders.finishdate, orders.reqquantity, orders.material, parts.TYPE,
parttypes.TYPE, orders.ordernumber, orders.operation,
orders.preoperation, orders.seqoperation, orders.projectcode,
orders.queuetime, orders.hoursworked, orders.operationtext,
orders.shorttext
FROM (((orders INNER JOIN workcenters ON orders.workcenter =
workcenters.code)
INNER JOIN
workcentersections ON workcenters.section = workcentersections.ID)
INNER JOIN
parts ON orders.material = parts.material)
INNER JOIN
parttypes ON parts.TYPE = parttypes.ID
Assuming your ORDERS table contains 15000 rows and your original query returns only 350 rows, you can replace your (INNER) JOINs with OUTER JOINs:
SELECT orders.plant, orders.workcenter, workcenters.occupied,
workcenters.section, workcentersections.section, orders.capacitycat,
orders.week, orders.earlieststartdate, orders.lateststartdate,
orders.useropstatus, orders.programstatus, orders.reqhours,
orders.finishdate, orders.reqquantity, orders.material, parts.TYPE,
parttypes.TYPE, orders.ordernumber, orders.operation,
orders.preoperation, orders.seqoperation, orders.projectcode,
orders.queuetime, orders.hoursworked, orders.operationtext,
orders.shorttext
FROM orders
LEFT OUTER JOIN workcenters ON orders.workcenter = workcenters.code
LEFT OUTER JOIN workcentersections
ON workcenters.section = workcentersections.ID
LEFT OUTER JOIN parts ON orders.material = parts.material
LEFT OUTER JOIN parttypes ON parts.TYPE = parttypes.ID
This will give you all rows from ORDERS (you might get duplicates if you haven't got strict 1:N relationships).
Then, you should replace the LEFT OUTER JOINs one-by-one with INNER JOINs and check the row count of each of these modified queries to find out which of the JOINs is responsible for the missing data.