query rows left join does not match ansi join equivalence rows - oracle

good evening,
I have 2 queries that return different row values, one with left join syntax and the other with old ansi
syntax that I need to create a materialized view in oracle. I need to add in the old syntax value1 (+) to
match the first left join query (which includes the nulls).
Thanks a lot.
Observation: the error occurs because the table "detalle_ordenes" has a value that does not exist in the table "tabla_hija". but I
want to show all rows without filtering it like in left Join query
select --(query number 1, returns 18 records.)
o.rowid o_rowid,
c.rowid c_rowid,
e.rowid e_rowid,
f.rowid f_rowid,
ordenid,
o.detalleid,
o.productoid,
f.vdescricion as v2descripcion
from detalle_ordenes o
left join tabla_hija c on o.estado=c.vvalor and c.tipo_filtro=1
left join tabla_hija e on o.segmento=e.vvalor and e.tipo_filtro=2
left join tabla_hija f on o.column1=f.vvalor and f.tipo_filtro=3
select --(query number 2, returns 15 records.)
o.rowid o_rowid,
c.rowid c_rowid,
e.rowid e_rowid,
f.rowid f_rowid,
ordenid,
o.detalleid,
o.productoid,
f.vdescricion as v2descripcion
from detalle_ordenes o, tabla_hija c, tabla_hija e,tabla_hija f
where
( o.estado=c.vvalor(+) and c.tipo_filtro=1 )
and
( o.segmento=e.vvalor(+) and e.tipo_filtro=2)
and
( o.column1=f.vvalor(+) and f.tipo_filtro=3)

Add (+) to all the conditions in the outer join filters:
select *
from detalle_ordenes o,
tabla_hija c,
tabla_hija e,
tabla_hija f
WHERE o.estado = c.vvalor (+)
AND 1 = c.tipo_filtro (+)
AND o.segmento = e.vvalor (+)
AND 2 = e.tipo_filtro (+)
AND o.column1 = f.vvalor (+)
AND 3 = f.tipo_filtro (+)
db<>fiddle here

Related

Error when running a sub query in Oracle SQL

I am trying to join three tables using a sub query.
The result of the first left outer join is to be used with another table to get a composite view with all attributes.
I am getting an error where the compile says, Unknown Command for the table in the second join clause.
When I create two independent views and then join then it works fine.
(select
l.ENROLLED_CONTENT,
l.LEARNING_ENROLLMENT_LEARNER,
l.EMPLOYEE_ID,
l.JOB_FAMILY_GROUP,
l.EMPLOYEE_TYPE,
l.JOB_FAMILY,
l.LEARNING_ENROLLMENT,
l.COMPLETION_STATUS,
l.COMPLETION_DATE,
l.EXPIRATION_DATE,
l.CF_LRV_LEARNING_CONTENT_NUMBER,
l.LEARNING_CONTENT_DETAIL,
l.LEARNING_CONTENT_TYPE,
l.LESSON_TYPE,
e.id# "WK_WORKER_ID"
from tgt_workday.learning l
left outer join ods_hrmaster.employee e
on l.EMPLOYEE_ID = e.employee#) t1
left outer join ( select
per_ids_id,
per_id,
id_pureid from
ods_pure.person_ids
) t2 on t1.wk_worker_id = t2.value where t2.type = 'Employee ID';
You can write it in a simple way. There is no need to make sub-queries as:
SELECT L.ENROLLED_CONTENT,
L.LEARNING_ENROLLMENT_LEARNER,
L.EMPLOYEE_ID,
L.JOB_FAMILY_GROUP,
L.EMPLOYEE_TYPE,
L.JOB_FAMILY,
L.LEARNING_ENROLLMENT,
L.COMPLETION_STATUS,
L.COMPLETION_DATE,
L.EXPIRATION_DATE,
L.CF_LRV_LEARNING_CONTENT_NUMBER,
L.LEARNING_CONTENT_DETAIL,
L.LEARNING_CONTENT_TYPE,
L.LESSON_TYPE,
E.ID# "WK_WORKER_ID"
FROM TGT_WORKDAY.LEARNING L
LEFT OUTER JOIN ODS_HRMASTER.EMPLOYEE E
ON L.EMPLOYEE_ID = E.EMPLOYEE#
LEFT OUTER JOIN ODS_PURE.PERSON_IDS T2
ON E.ID# = T2.VALUE
AND T2.TYPE = 'Employee ID';
Once you use the outer joined table's column in WHERE clause, It will result in the same result as inner join(there is another ways to use it in WHERE clause though). So it is better to avoid using outer joined table's column in the WHERE clause.
Try as
SELECT *
FROM ( (SELECT l.ENROLLED_CONTENT,
l.LEARNING_ENROLLMENT_LEARNER,
l.EMPLOYEE_ID,
l.JOB_FAMILY_GROUP,
l.EMPLOYEE_TYPE,
l.JOB_FAMILY,
l.LEARNING_ENROLLMENT,
l.COMPLETION_STATUS,
l.COMPLETION_DATE,
l.EXPIRATION_DATE,
l.CF_LRV_LEARNING_CONTENT_NUMBER,
l.LEARNING_CONTENT_DETAIL,
l.LEARNING_CONTENT_TYPE,
l.LESSON_TYPE,
e.id# "WK_WORKER_ID"
FROM tgt_workday.learning l
LEFT OUTER JOIN ods_hrmaster.employee e
ON l.EMPLOYEE_ID = e.employee) t1
LEFT OUTER JOIN
(SELECT per_ids_id, per_id, id_pureid FROM ods_pure.person_ids) t2
ON t1.wk_worker_id = t2.VAL AND t2.TYPE = 'Employee ID')

join three tables with count and sum in oracle

I have three tables and trying to join these tables with count(working_days) and sum(Overtime) functions but overtime is not showing correct i am trying the query is.
SELECT E.EMP_CODE,E.EMP_NAME,
COALESCE(SUM(O.OVERTIME),0) AS OVERTIME,COALESCE(COUNT(C.EMP_ATT),0) WORKED_DAYS
FROM EMP E
LEFT JOIN OVERTIME O
ON E.EMP_CODE = O.EMP_CODE
LEFT JOIN ATT_REG C
ON E.EMP_CODE=C.EMP_CODE
GROUP BY E.EMP_CODE,E.EMP_NAME
ORDER BY EMP_CODE
Yes, You will get multiple records of the overtime for employees as shift date (or similar in your table) is missing in the join.
SELECT E.EMP_CODE,E.EMP_NAME,
COALESCE(SUM(O.OVERTIME),0) AS OVERTIME,
COALESCE(COUNT(C.EMP_ATT),0) WORKED_DAYS
FROM EMP E
LEFT JOIN ATT_REG C
ON E.EMP_CODE=C.EMP_CODE
LEFT JOIN OVERTIME O
ON E.EMP_CODE = O.EMP_CODE
AND C.SHIFTDATE = O.SHIFDATE -- YOU NEED SOMETHING LIKE THIS
GROUP BY E.EMP_CODE,E.EMP_NAME
ORDER BY EMP_CODE

Left outer join is null- additional conditions

I'm trying to find all entries in table a, where there is no matching entry in table b for one specific column (order). I'm using the following:
SELECT *
FROM a
LEFT OUTER JOIN b
ON a.id = b.id
WHERE b.order IS NULL
AND a.result>10
However, the last condition for result doesn't seems to work. It simply lists all the entries from table a, regardless whether result is more than 10 or not.
Any way around this?
Shouldn't your query be as below?
SELECT * FROM a LEFT OUTER JOIN b ON a.id = b.id WHERE b.id IS NULL AND a.result>10

Multiple Joins LINQ Query performance

I'm new to LINQ and have very little knowledge.
I have the following complex query. it runs 3 or 4 times slower than the stored procedure which i translated to LINQ.
any tips for me to make it run faster?
var result = from a in db.A
join al in db.AL.Where(q => q.CurrentLocation == 1) on a.AID equals al.AID into tmp_al
from al in tmp_al.DefaultIfEmpty()
join l in db.Lon al.LID equals l.LID into tmp_l
from l in tmp_l.DefaultIfEmpty()
join r in db.R on l.RID equals r.RID into tmp_r
from r in tmp_r.DefaultIfEmpty()
join b in db.B on r.BID equals b.BID into tmp_b
from b in tmp_b.DefaultIfEmpty()
join ap in db.AP.Where(q => q.CurrentProtocol == 1) on a.AID equals ap.AID into tmp_ap
from ap in tmp_ap.DefaultIfEmpty()
join p in db.P on ap.PID equals p.PID into tmp_p
from p in tmp_p.DefaultIfEmpty()
join s in db.S on a.SID equals s.SID into tmp_s
from s in tmp_s.DefaultIfEmpty()
join ans in db.AS on a.ASID equals ans.ASID into tmp_ans
from ans in tmp_ans.DefaultIfEmpty()
join pr in db.P on p.PI equals pr.PID into tmp_pr
from pr in tmp_pr.DefaultIfEmpty()
where a.Active == 1
group a by new { a.Active, pr.LN, pr.FN, b.BN, r.RID, r.R1, p.PN, s.S1, ans.AS1 }
into grp
orderby grp.Key.BN, grp.Key.R1, grp.Key.PN, grp.Key.S1, grp.Key.AS1
select new
{
PIName = grp.Key.LN + " " + grp.Key.FN,
BN = grp.Key.BN,
RID = grp.Key.RID,
R = grp.Key.R1,
PN = grp.Key.PN,
S = grp.Key.S1,
AS = grp.Key.AS1,
NumberOA = grp.Count()
};
Thanks for your answers. #Albin Sunnanbo: i dont know how to check the execution plans. my LINQ runs correctly and produces the required output. it is just slow. I would like to speeden it up. #usr: the original sql is as follows:
sorry about the silly table names. the original code is confidential. so i'm not posting the complete table names.
CREATE PROCEDURE [dbo].[report_CBRP] --
AS
SELECT LN + ' ' + FN As PIN, BN, R.RID, R, PN,
S, AS, COUNT(*) As NOA
FROM A
LEFT JOIN AL
ON A.AID = AL.AID
AND AL.CL = 1
LEFT JOIN L
ON AL.LID = L.LID
LEFT JOIN R
ON L.RID = R.RID
LEFT JOIN B
ON R.BID = B.BID
LEFT JOIN AP
ON A.AID = AP.AID
AND AP.CPl = 1
LEFT JOIN P
ON AP.PID = P.PID
LEFT JOIN S
ON A.SID = S.SID
LEFT JOIN AS
ON A.ASID = AS.ASID
LEFT JOIN P
ON P.PI = P.PID
GROUP BY A.A, LN , FN , B.BN, R.RID, R.R, P.PN,
S.S, AS.AS
HAVING A.A = 1
ORDER BY B.BN, R.R, P.PN, S, AS
GO
It seems you're doing SQL hard life here.
In general, try to avoid so many joins, but rather break them into few small queries.
More than that, you're performing a group by which in itself is an expensive operation, let alone with so many columns
I've noticed that you're joining all the columns in each table. Try to select only the relevant columns.
Also noticed that few of the tables aren't used in the group by like al, ap and l. Do you need them at all??
Use AsNoTracking() for readonly data from EF. In that way you speed up things.
Use SQL Views

Linq query only returning 1 row

Dim ds = From a In db.Model
Join b In db.1 On a.id Equals b.ID
Join c In db.2 On a.id Equals c.ID
Join d In db.3 On a.id Equals d.ID
Join f In db.4 On a.id Equals f.ID
Select a.id, a.Ref, a.Type, a.etc
Above is my linq query. At the moment I am only getting the first row from the db returned when there are currently 60 rows. Please can you tell me where I am going wrong and how to select all records.
Thanks in advance!
UPDATE:
When I take out all the joins like so:
Dim ds = From a In db.1, b In db.2, c In db.3, d In db.4, f In db.5
Select a.id, a.Ref, a.type, b.etc, c.etc, d.etc
I get a system.outofmemory exception!
You're only going to get a row produced when all of the joins match - in other words, when there's a row from Model with an AP, an Option, a Talk and an Invoice. My guess is that there's only one of those.
LINQ does an inner join by default. If you're looking for a left outer join (i.e. where a particular row may not have an Invoice, or a Talk etc) then you need to use a group join, usually in conjunction with DefaultIfEmpty.
I'm not particularly hot on VB syntax, but this article looks like it's what you're after.

Resources