Could anyone suggest please is it possible to break recursion function if circular dependency happend ? As soon as I encounter that s.Part_Ptr = s.Substituent_Ptr I want to break Loop and return result.
with SubstitutionRecursion as (select Part_Ptr, Substituent_Ptr from model_2271_substitute where Part_Ptr = 24588687861243
union all
select s.Part_Ptr, s.Substituent_Ptr from SubstitutionRecursion sr
left join model_2271_substitute s on s.Part_Ptr = sr.Substituent_Ptr
where s.Substituent_Ptr is not null)
select p.partCode, p.partDescription, p.notes from SubstitutionRecursion sr
left join model_2271_all_parts p on p.PartPtr = sr.Substituent_Ptr;
You would typically keep track of the visited nodes in another column of the CTE, and stop the recursion when an already visited node is met.
Your question does not show sample data, which makes it a bit more complicated to answer, but the logic would look like:
with substitutionrecursion as (
select part_ptr, substituent_ptr, '/' || substituent_ptr || '/' path
from model_2271_substitute
where part_ptr = 24588687861243
union all
select s.part_ptr, s.substituent_ptr, sr.path || s.substituent_ptr || '/'
from substitutionrecursion sr
inner join model_2271_substitute s on s.part_ptr = sr.substituent_ptr
where s.substituent_ptr not like '%/' || sr.path || '/%'
)
select ...
path is a string column that concatenates the visited substituent_ptrs.
Related
for some reasons I don't have, a table, although referenced in the query, is not referenced according to the error.
The query :
WITH RECURSIVE temptable AS (
SELECT part_id, tracability_component1, tracability_component2, tracability_component3, tracking_id
FROM kpitr.subop_result SR
LEFT JOIN kpitr.part_produce PP ON PP.supplier_id || PP.product_id LIKE SR.tracability_component1 OR PP.supplier_id || PP.product_id LIKE SR.tracability_component2 OR PP.supplier_id || PP.product_id LIKE SR.tracability_component3
WHERE part_id LIKE '%0005001723A031T'
UNION ALL
SELECT SR2.part_id, SR2.tracability_component1, SR2.tracability_component2, SR2.tracability_component3, PP2.tracking_id
FROM kpitr.subop_result SR2, temptable
LEFT JOIN kpitr.part_produce PP2 ON PP2.supplier_id || PP2.product_id LIKE SR2.tracability_component1 OR PP2.supplier_id || PP2.product_id LIKE SR2.tracability_component2 OR PP2.supplier_id || PP2.product_id LIKE SR2.tracability_component3 OR SR2.part_id LIKE temptable.tracking_id
)
SELECT * FROM temptable
The error :
ERROR: invalid reference to FROM-clause entry for table "sr2"
LINE 9: ...uce PP2 ON PP2.supplier_id || PP2.product_id LIKE SR2.tracab...
^
HINT: There is an entry for table "sr2", but it cannot be referenced from this part of the query.
SQL state: 42P01
Character: 678
I believe I place in the wrong order something, or I missed sometinh, but after some tests, it didn't change anything.
Could you help me ?
Got the solution, after some tries :
WITH RECURSIVE temptable AS (
SELECT SR1.part_id, SR1.tracability_component1, SR1.tracability_component2, SR1.tracability_component3, PP1.tracking_id
FROM kpitr.subop_result SR1
LEFT JOIN kpitr.part_produce PP1 ON UPPER(PP1.reference) || UPPER(PP1.product_id) = UPPER(SR1.tracability_component1) OR UPPER(PP1.reference) || UPPER(PP1.product_id) = UPPER(SR1.tracability_component2) OR UPPER(PP1.reference) || UPPER(PP1.product_id) = UPPER(SR1.tracability_component3)
WHERE part_id LIKE '%0005001723A031T'
UNION ALL
SELECT sr.part_id, sr.tracability_component1, sr.tracability_component2, sr.tracability_component3, pp.tracking_id
FROM kpitr.subop_result sr
JOIN temptable ON UPPER(sr.part_id) = UPPER(temptable.tracability_component1) OR UPPER(sr.part_id) = UPPER(temptable.tracability_component2) OR UPPER(sr.part_id) = UPPER(temptable.tracability_component3) OR UPPER(sr.part_id) = UPPER(temptable.tracking_id)
LEFT JOIN kpitr.part_produce pp ON UPPER(pp.reference) || UPPER(pp.product_id) = UPPER(sr.tracability_component1) OR UPPER(pp.reference) || UPPER(pp.product_id) = UPPER(sr.tracability_component2) OR UPPER(pp.reference) || UPPER(pp.product_id) = UPPER(sr.tracability_component3)
)
SELECT * FROM temptable
I'm making a query with multiple UNION ALL statements and it's not showing all the results it should show. The SELECT statements all have the same amount of columns, the same aliases and same data types (I've already tried to use CAST, just to be sure). There's only a single SELECT statement that's using a CASE in two different columns and that is all that's different from the others. I've tried to derive that to a sub-select, but to no avail. If I run them by themselves they work fine, matter of fact. If I remove this SELECT statement that has those two CASE's and leave all the rest, it runs fine. There's a lot of unions, so I'll just post the problematic SELECT and one of the other UNION's, since they're all pretty much the same.
All I'm doing in these is pulling values from different events, like employee's taxes, employee's salaries and different adjustments, just to give a clearer view of what I'm doing. I can't provide the real data due to legal reasons. What 's making it not run along the other SELECTs?
Here's the one that's giving me issues
SELECT
CASE
WHEN TCL.CONTADEB IS NOT NULL THEN TCL.CONTADEB
WHEN TCL.CONTACRED IS NOT NULL THEN TCL.CONTACRED
END AS CONTA_CTB
, CASE
WHEN TCL.CONTADEB IS NOT NULL THEN CR.VALOREVENTO
END AS DEBITO
, CASE
WHEN TCL.CONTACRED IS NOT NULL THEN CR.VALOREVENTO
END AS CREDITO
, FP.NOMEFUNC AS FUNCIONARIO
, EV.DESCREVENTO || ' - ' || EXTRACT(MONTH FROM PC.COMPET) || '/' || EXTRACT(YEAR FROM PC.COMPET) || ' ' || FP.NOMEFUNC AS OBSERVACAO
, LCTB.DESCRLOCALCTB AS LOCAL_CONTABIL
, CC.DESCRCENTROCUSTO AS CENTRO_CUSTO
, EXTRACT(YEAR FROM PC.DATAFINALFOLHA) || lpad(EXTRACT(MONTH FROM PC.DATAFINALFOLHA), '2', '0') || EXTRACT(DAY FROM PC.DATAFINALFOLHA) AS VENCIMENTO
FROM CALCULORATEIO CR
LEFT JOIN CENTROCUSTO CC
ON CC.CODIGOEMPRESA = CR.CODIGOEMPRESA AND CC.CODIGOCENTROCUSTO = CR.CODIGOCENTROCUSTO
LEFT JOIN EVENTO EV
ON EV.CODIGOEVENTO = CR.CODIGOEVENTO
LEFT JOIN PERIODOCALCULO PC
ON PC.CODIGOEMPRESA = CR.CODIGOEMPRESA AND PC.CODIGOPERCALCULO = CR.CODIGOPERCALCULO
LEFT JOIN FUNCCONTRATO FC
ON FC.CODIGOEMPRESA = CR.CODIGOEMPRESA AND FC.CODIGOFUNCCONTR = CR.CODIGOFUNCCONTR
LEFT JOIN FUNCPESSOA FP
ON FP.CODIGOFUNCPESSOA = FC.CODIGOFUNCPESSOA
LEFT JOIN FUNCLOCALCTB FLC
ON FLC.CODIGOEMPRESA = CR.CODIGOEMPRESA AND FLC.CODIGOFUNCCONTR = CR.CODIGOFUNCCONTR
AND FLC.DATAOPCAO = (SELECT MAX(FLC1.DATAOPCAO) FROM FUNCLOCALCTB FLC1 WHERE FLC1.CODIGOEMPRESA = FLC.CODIGOEMPRESA AND
FLC1.CODIGOFUNCCONTR = FLC.CODIGOFUNCCONTR AND FLC1.DATAOPCAO <= PC.DATAINICIALFOLHA)
LEFT JOIN LOCALCONTABIL LCTB
ON LCTB.CODIGOEMPRESA = FLC.CODIGOEMPRESA AND LCTB.CODIGOLOCALCTB = FLC.CODIGOLOCALCTB
LEFT JOIN EVENTOTABELACONTABIL EVT
ON EVT.CODIGOEVENTO = CR.CODIGOEVENTO AND EVT.CODIGOGRUPOTABELACONTABIL = 0
LEFT JOIN TABCTBLOCALCTB TCL
ON TCL.CODIGOEMPRESA = FLC.CODIGOEMPRESA AND TCL.CODIGOTABCTB = EVT.CODIGOTABCTB AND TCL.CODIGOLOCALCTB = FLC.CODIGOLOCALCTB
WHERE
CR.CODIGOEMPRESA = :CodigoEmpresa.n AND
CR.CODIGOPERCALCULO = :CodigoPerCalculo.n
And here's one of the others:
SELECT
CASE
WHEN PFR.DIFERPGTO > 0 THEN '1608'
ELSE '1612'
END AS CONTA_CTB
, PFR.DIFERPGTO AS DEBITO
, PFR.DIFERPGTO AS CREDITO
, FP.NOMEFUNC AS FUNCIONARIO
, 'Diferença Pgto 13' || ' - ' || EXTRACT(MONTH FROM PC.COMPET) || '/' || EXTRACT(YEAR FROM PC.COMPET) || ' ' || FP.NOMEFUNC AS OBSERVACAO
, LCTB.DESCRLOCALCTB AS LOCAL_CONTABIL
, CC.DESCRCENTROCUSTO AS CENTRO_CUSTO
, EXTRACT(YEAR FROM PC.DATAFINALFOLHA) || lpad(EXTRACT(MONTH FROM PC.DATAFINALFOLHA), '2', '0') || EXTRACT(DAY FROM PC.DATAFINALFOLHA) AS VENCIMENTO
FROM PROVISAO13RAT PFR
LEFT JOIN FUNCCONTRATO FC
ON FC.CODIGOEMPRESA = PFR.CODIGOEMPRESA AND FC.CODIGOFUNCCONTR = PFR.CODIGOFUNCCONTR
LEFT JOIN FUNCPESSOA FP
ON FP.CODIGOFUNCPESSOA = FC.CODIGOFUNCPESSOA
LEFT JOIN PERIODOCALCULO PC
ON PC.CODIGOEMPRESA = PFR.CODIGOEMPRESA AND PC.COMPET = PFR.COMPET
LEFT JOIN CENTROCUSTO CC
ON CC.CODIGOEMPRESA = PFR.CODIGOEMPRESA AND CC.CODIGOCENTROCUSTO = PFR.CODIGOCENTROCUSTO
LEFT JOIN FUNCLOCALCTB FLC
ON FLC.CODIGOEMPRESA = PFR.CODIGOEMPRESA AND FLC.CODIGOFUNCCONTR = PFR.CODIGOFUNCCONTR
AND FLC.DATAOPCAO = (SELECT MAX(FLC1.DATAOPCAO) FROM FUNCLOCALCTB FLC1 WHERE FLC1.CODIGOEMPRESA = FLC.CODIGOEMPRESA AND
FLC1.CODIGOFUNCCONTR = FLC.CODIGOFUNCCONTR AND FLC1.DATAOPCAO <= PC.DATAINICIALFOLHA)
LEFT JOIN LOCALCONTABIL LCTB
ON LCTB.CODIGOEMPRESA = FLC.CODIGOEMPRESA AND LCTB.CODIGOLOCALCTB = FLC.CODIGOLOCALCTB
WHERE
PFR.CODIGOEMPRESA = :CODIGOEMPRESA.n AND
PFR.COMPET = :DATAINICIAL.d AND
PFR.DIFERPGTO <> 0
The main tables I'm using in these all have the same structures, with exception of that one (the first code I've pasted here), could this be part of the problem?
The WHERE clauses all filter through company code and billing date, that's the same for all of them. If any information is lacking, I'll provide them the best way I can.
Ok, so it turns out it was because of the table's structures that were different, doesn't really make much sense for me, but it's working now
I am having issues with combining two columns into the one using mssql
table 1 format:
|| WJCPrefix || WJCNo ||
|| UK-R/SWJC/14/ || 1234 ||
|| UK-R/CUWJC/14/ || 2345 ||
|| UK-R/CUWJC/14/ || 3456 ||
|| UK-R/SWJC/14/ || 4567 ||
|| UK-R/CUWJC/14/ || 5678 ||
The desired out would be:
UK-R/CUWJC/14/3456
UK-R/CUWJC/14/5678
the sql statement i am using is:
SELECT tblWJCItem.AddedDescription, concat(tblWJC.WJCPrefix, tblWJC.WJCNo) AS OurRef
FROM tblWJC
INNER JOIN tblWJCItem ON tblWJC.WJCID = tblWJCItem.WJCID;
I've also used:
SELECT tblWJCItem.AddedDescription, tblWJC.WJCPrefix + '' + tblWJC.WJCNo AS OurRef
FROM tblWJC
INNER JOIN tblWJCItem ON tblWJC.WJCID = tblWJCItem.WJCID;
I can't seem to connect these two columns could anyone point out what I am doing wrong here?
Thanks
Your first query (Concat() function) should work if you are using SQL Server 2012 or later.
For other versions, you may need to Convert()/Cast() WJCNo to a string type
SELECT t2.AddedDescription,
t1.WJCPrefix + CONVERT(Varchar(10),t1.WJCNo) AS OurRef
FROM tblWJC t1
INNER JOIN tblWJCItem t2 ON t1.WJCID = t2.WJCID;
Your first query should be fine. But you might try:
SELECT tblWJCItem.AddedDescription, tblWJC.Prefix + cast(tblWJC.WJCNo as varchar(255)) AS OurRef
FROM tblWJC INNER JOIN
tblWJCItem
ON tblWJC.WJCID = tblWJCItem.WJCID;
You might get an error in the second version if WJCno is numeric rather than a string.
I think WJCNo is numeric or int field so Convert this field to Varchar first then concat:-
SELECT tblWJCItem.AddedDescription,
tblWJC.WJCPrefix + '' + CONVERT(Varchar(10),tblWJC.WJCNo) AS OurRef
FROM tblWJC
INNER JOIN tblWJCItem ON tblWJC.WJCID = tblWJCItem.WJCID;
I've come across a strange behavior that I can't diagnose.
I've got an Oracle Database (11g) and I've built a view within this database. This view returns a list of information which was fine before the issue and is currently fine after the issue.
Let's say that this view returns 10 rows. When I run an aggregate function over this view, e.g. lets say a COUNT(*) I get a list of 10 rows each displaying 'Null' instead of one row with the number 10.
This was an issue that started abruptly without me knowingly making changes to the database or the view (however this is a big corporate database and changes could have been made, by a select few other people - all of which are currently denying any changes were made) There are also no know triggers that effect the view
This issue does not appear in other tables or other views. I've tried running an aggregate function on each table or view that makes up the final view and each of those returns a single number as expected.
I'm not sure what else to try. My Google searches are not offering any leads either. I would upload the code, but it is large and unwieldy, I also couldn't begin to explain how it was looking at data (suffice it to say that the database is French built)
What is really getting me is the fact that the view returns the data as expect but when I run an aggregate function over it (e.g. SELECT COUNT(*) FROM VIEW_THAT_IS_FAILING) it fails in this weird way. Any ideas?
View that is failing definition:
SELECT x.OBJEXCDE,
x.OBJDSC,
x.CLASSIFICATION,
x.COUNTRY,
NVL(y.MONTH_USAGE, 0) AS MONTH_USAGE,
x.STKQTY,
x.STANDARD_COST
FROM (SELECT a.OBJINCDE, a.OBJEXCDE, a.OBJDSC, NVL(b.STKQTY, 0) AS STKQTY, NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST, NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
CASE WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') = ' 0615 130' THEN 'UK'
ELSE 'IRE' END AS COUNTRY
FROM P_OBJ a, P_OBJSTORE b, P_OBJPRC c,
(SELECT a.OBJINCDE, b.OBJCHARVAL
FROM P_OBJ a, (SELECT OBJINCDE, OBJCHARVAL FROM P_OBJCHAR WHERE CHARINCDE = 524) b
WHERE a.OBJINCDE = b.OBJINCDE (+)) d
WHERE a.OBJINCDE = b.OBJINCDE (+)
AND a.OBJINCDE = c.OBJINCDE (+)
AND a.OBJINCDE = d.OBJINCDE (+)
AND TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284')
AND a.CLASSINCDE IN (83, 84, 126) --New Parts, Repairable Parts, Installation Parts
AND (d.OBJCHARVAL IS NULL OR NVL(c.OBJPRC1VAL, 0) = 0)) x,
W_USAGE_1_MONTH y
WHERE x.OBJINCDE = y.OBJINCDE (+)
AND x.COUNTRY = y.COUNTRY (+)
AND (NVL(y.MONTH_USAGE, 0) + x.STKQTY) > 0
Definition for W_USAGE_1_MONTH:
SELECT a.OBJINCDE,
a.OBJEXCDE,
a.OBJDSC,
NVL(b.STKQTY, 0) AS STKQTY,
NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST,
NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
CASE WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') = ' 0615 130' THEN 'UK' ELSE 'IRE' END AS COUNTRY
FROM P_OBJ a,
P_OBJSTORE b,
P_OBJPRC c,
(SELECT a.OBJINCDE, b.OBJCHARVAL FROM P_OBJ a, (SELECT OBJINCDE, OBJCHARVAL FROM P_OBJCHAR WHERE CHARINCDE = 524) b WHERE a.OBJINCDE = b.OBJINCDE (+)) d
WHERE a.OBJINCDE = b.OBJINCDE (+)
AND a.OBJINCDE = c.OBJINCDE (+)
AND a.OBJINCDE = d.OBJINCDE (+)
AND TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284')
AND a.CLASSINCDE IN (83, 84, 126) --New Parts, Repairable Parts, Installation Parts
AND (d.OBJCHARVAL IS NULL OR NVL(c.OBJPRC1VAL, 0) = 0)
Just for fun, try the following:
SELECT x.OBJEXCDE,
x.OBJDSC,
x.CLASSIFICATION,
x.COUNTRY,
NVL(y.MONTH_USAGE, 0) AS MONTH_USAGE,
x.STKQTY,
x.STANDARD_COST
FROM (SELECT a.OBJINCDE,
a.OBJEXCDE,
a.OBJDSC,
NVL(b.STKQTY, 0) AS STKQTY,
NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST,
NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
CASE
WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') = ' 0615 130' THEN 'UK'
ELSE 'IRE'
END AS COUNTRY
FROM P_OBJ a
LEFT OUTER JOIN P_OBJSTORE b
ON (a.OBJINCDE = b.OBJINCDE)
LEFT OUTER JOIN P_OBJPRC c
ON (a.OBJINCDE = c.OBJINCDE)
LEFT OUTER JOIN (SELECT a.OBJINCDE, b.OBJCHARVAL
FROM P_OBJ a
LEFT OUTER JOIN (SELECT OBJINCDE, OBJCHARVAL
FROM P_OBJCHAR
WHERE CHARINCDE = 524) b
ON (a.OBJINCDE = b.OBJINCDE)) d
ON (a.OBJINCDE = d.OBJINCDE)
WHERE TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284') AND
a.CLASSINCDE IN (83, 84, 126) AND --New Parts, Repairable Parts, Installation Parts
(d.OBJCHARVAL IS NULL OR
NVL(c.OBJPRC1VAL, 0) = 0)) x
LEFT OUTER JOIN W_USAGE_1_MONTH y
ON (x.OBJINCDE = y.OBJINCDE AND
x.COUNTRY = y.COUNTRY)
WHERE (NVL(y.MONTH_USAGE, 0) + x.STKQTY) > 0
which is just the original view reworked to use ANSI join syntax. Give it a try and see if it changes anything.
It could also be that the DBA's applied a patch or made some other change which is affecting this.
Share and enjoy.
While the support request still hasn't been responded to, I had a crack at figuring out this problem.
While breaking the view back to it's essentials I found that when when I was attempting to make a aggregation of a smaller aggregate part the SQL was failing. So the aggregation in W_USAGE_1_MONTH was causing the aggregation of the larger few to fail in a way that would out put a series of NULL values to the count of how many rows, instead of one line with the number of counted rows.
While I did a bunch of tinkering with the view what appears to have fixed the behavior was when I encapsulated the W_USAGE_1_MONTH in a FROM Clause Select statement:
(SELECT OBJINCDE, MONTH_USAGE, COUNTRY FROM W_USAGE_1_MONTH) b
My feeling is that the DBA (whom I don't have immediate access to) made a change that had an effect on the order of processing SQL statements. Forcing the the W_USAGE_1_MONTH view to be evaluated before it is used by the statement results in the operation successfully completing.
Not a very exciting end to a strange occurrence and an answer that doesn't explain the underlying cause as I don't know what changes could have been made that effect evaluation order of statements. However perhaps this would help someone else to look at evaluation order for weird behavior.
I've got the following query.
The only "left" table is the one with the alias "o".
I want to specify the following. How can I do? Should I use a WITH temp construct?
AND ( NVL (domb.DOMB_CONTO_CORRENTE, ' ') != o.campo43
OR NVL (abi.abi_descrizione, ' ') != o.campo41
OR NVL (cab.cab_descrizione, ' ') != o.campo42)
Here's the complete statement:
SELECT /*+ parallel(o 64) */
o.stato, COUNT (1)
FROM CONF_RAGGRUPPAMENTI_FORN rgf,
CRD_RID_REL_DOMICILIAZIONE crrd,
CRD_DOMICILIAZIONI domb,
uff_abi abi,
uff_abi_cab cab,
CONTO_CLIENTE_T809 o,
eni_flussi_hub c,
eni_monitor mon
WHERE 1 = 1
--RGF - OUT
AND rgf.RGF_CODICE_RAGGRUPPAMENTO(+) = o.campo1
--Join tra OUT e la ENI_FLUSSI_HUB
AND o.id_messaggio = c.flh_id_messaggio(+)
AND o.d_pubblicazione = c.flh_data_elaborazione(+)
--Join tra ENI_FLUSSI_HUB e ENI_MONITOR
AND c.FLH_ID_MESSAGGIO = MON.MON_ID_MESSAGGIO(+)
AND c.FLH_TIPO_PROCESSO_COD = MON.MON_COD_TP_PROCESSO(+)
AND c.flh_flag_ann(+) = 'N'
AND mon_flag_ann(+) = 'N'
--Join da RGF a DOMB
AND rgf.UITR_IDENT_TIPI_RAGGR_ID(+) = 'MP'
AND rgf.RGF_RAGGRUPPAMENTO_FORN_ID = crrd.RGF_RAGGRUPPAMENTO_FORN_ID(+)
AND crrd.DOMB_DOMICILIAZIONE_ID = domb.DOMB_DOMICILIAZIONE_ID(+)
AND CRRD.CRRD_RID_REL_DOM_ID = crrd.crrd_storico_id
AND CRRD.CRRD_FLAG_ANN (+) = 'N'
AND domb.domb_flag_ann (+) = 'N'
AND rgf.rgf_flag_ann(+) = 'N'
--Join tra domb e abi e cab
AND DOMB.ABI_ID = abi.ABI_ID(+)
AND DOMB.CAB_ID = cab.CAB_ID(+)
--Filtro sulle date
AND o.d_pubblicazione BETWEEN TO_DATE ('06-apr-2013')
AND TO_DATE ('14-apr-2013')
--Solo i flussi che producono variazioni
AND ( NVL (domb.DOMB_CONTO_CORRENTE, ' ') != o.campo43
OR NVL (abi.abi_descrizione, ' ') != o.campo41
OR NVL (cab.cab_descrizione, ' ') != o.campo42)
GROUP BY o.stato
If you can, I would recommend rewriting your query in modern ANSI syntax. This makes the query not only more readable, but it's easier to apply predicates on the optional table in a clear manner. I've rewritten 'old' Oracle queries and it's usually a quick cut and paste job to move the join conditions from the WHERE clause to the FROM ... JOIN ... ON ... clause.
Then, any predicates that apply to the optional table are listed under the OUTER JOIN condition, not under the WHERE. For example (in a very rough example):
SELECT
mt.col1,
mt.col2,
ot.col3
-- other columns ...
FROM main_table mt
LEFT OUTER JOIN optional_table ot ON mt.col1 = ot.col1
AND ot.col2 = 'N'
AND NVL (ot.some_column, 'x') != mt.col5
-- Now the where for the result set and main table
WHERE
AND mt.col4 BETWEEN TO_DATE ('06-apr-2013') AND TO_DATE ('14-apr-2013')
-- Other conditions on the total result set.
I've found this easiest way to apply conditions to the optional table without excluding rows from the final set.
You do not need to use the + on the NVLs because you establish the outer join already on the ID of domp, abi, and cab.
I agree with the others that using JOIN statement makes more readable SQL Selects.
Do you have any trouble with the query?