how to use nvl on a regexp_like product - oracle

please can someone help with a SQL problem?
I have a query which currently accepts an external parameter which can be null or a single value such as 'STR1' .
This is handled by a query in format below:
select a.refe_id from a, b, c
where a.owln_code = c.code
and c.con_id = b.pers_id
and b.con_abbrv = nvl(:PARAM, b.con_abbrv)
and a.status = '01'
In the future the external parameter can have a single value, null, or multiple values separated by pipes e.g STR1|STR2|STR3|
I am now at the stage below in accomodating this but have lost the nvl test that allows a match through all rows in table b if the parameter is null.
Please can someone help with how to do this? I have searched the net and tried to do it myself. Thanks very much in advance.
select a.refe_id from a, b, c
where a.owln_code = c.code
and c.con_id = b.pers_id
and regexp_like(:PARAM, '(^|)' || b.con_abbrv|| '(|$)')
and a.status = '01'

I'd recommend something like this:
select a.refe_id from a, b, c
where a.owln_code = c.code
and c.con_id = b.pers_id
and (:PARAM IS NULL OR regexp_like(:PARAM, '(^|)' || b.con_abbrv|| '(|$)'))
and a.status = '01'
Not related, but I'd also recommend using explicit join syntax: I think you'll find it makes the query easier to read because it separates the JOIN logic from the WHERE logic:
select a.refe_id from a
join c on a.owln_code = c.code
join b on c.con_id = b.pers_id
where (:PARAM IS NULL OR regexp_like(:PARAM, '(^|)' || b.con_abbrv|| '(|$)'))
and a.status = '01'

Related

Percentile_Cont function throwing error

I have this query where I am trying to introduce a non-static value into PERCENTILE_CONT:
SELECT perf2.REVIEW_PERIOD
, PERCENTILE_CONT(goalsASP.GOAL*.01) WITHIN GROUP (ORDER BY AVG_AMT ASC) ast75
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD
The error thrown is:
ORA-30497: Argument should be a constant or a function of expressions in GROUP BY.
30497. 00000 - "Argument should be a constant or a function of expressions in GROUP BY."
This is in a view, it was working fine when goalsASP.GOAL*.01 was .75 and I have a stored procedure where feeding a column as an argument works just fine so I'm kind of at a loss for what I'm doing wrong here.
Got it. It's not so much a problem of Percentile_Cont, it's a problem of correct grouping.
To troubleshoot I isolated goalsASP.GOAL
SELECT perf2.REVIEW_PERIOD
, goalsASP.GOAL
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD
Then it became obvious that I needed to also group by goalsASP.GOAL.
So, then, the answer is:
SELECT perf2.REVIEW_PERIOD
, PERCENTILE_CONT(goalsASP.GOAL*.01) WITHIN GROUP (ORDER BY AVG_AMT ASC) ast75
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD,
goalsASP.GOAL
Kind of embarrassing that I didn't see that before, but tired eyes miss this stuff.

ORDER BY inside Decode Oracle Function

I try to use ORDER BY inside the Oracle Decode function
The compiler says missing right parenthesis
DECODE(controlNumber, NULL, myOldNUmber, (SELECT myNewNumber FROM tableA A, tableB B WHERE A.control_id = B.control_id AND A.other_id = B.other_id) ) AS finalnumber,
Seems it is the same query did not see why the ORDER BY is not accepted here:
DECODE(controlNumber, NULL, myOldNUmber, (SELECT myNewNumber FROM tableA A, tableB B WHERE A.control_id = B.control_id AND A.other_id = B.other_id ORDER BY createdTime)) AS finalnumber,
I am not able to test currently, but please try...
DECODE(controlNumber, NULL, myOldNUmber, (SELECT myNewNumber FROM (SELECT myNewNumber FROM tableA A, tableB B WHERE A.control_id = B.control_id AND A.other_id = B.other_id ORDER BY createdTime) WHERE rownum=1) AS finalnumber

Linq outer joins

I need help to convert the following query to Linq
SELECT c.Code, c.Name
from tblCodes as c
where c.code not in
(select Code from npConsultant where ConsultantName = 'X')
and c.Code < 'AA.0000'
When I try in Linqpad it doesn't seem to understand the into or defaultifempty. Maybe these are inproper methods for what I need to do
Simple answer is use the "let" keyword and generate a sub-query that supports your conditional set for the main entity.
var Objlist= from u in tblCodes
let ces = from ce in npConsultant
select ce.code
where !ces.Contains(u.code)
select u;
try something like that:
var query =
from c in Customers
where !(from n in npConsultant
where n.ConsultantName='X'
select n.Code)
.Contains(c.Code)
&& c.Code < 'AA.0000'
select c.Code, c.Name;
I just do not get how Code can be less than 'AA.0000' ....

Why sub SQL in FROM area can't be null?

select col_1,
col_2
from tbl_a A,
tbl_b B,
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
where A.col_1 = B.col_1
and A.col_2 = B.col_2
and (A.col_2 = B.col_2
or C.col_2 = A.col_2);
My environment is Oracle,when I run this SQL,if the sub SQL C hasn't got a result,then the entire SQL returns NULL.Whereas if C has a result(not null) which fits other condions,there could be a result.Would somebody explain why sub SQL at the from area need to be not NULL?Thanks very much.
You need to bring yourself into the 90s and start using standard joins:
select col_1,
col_2
from tbl_a A
inner join
tbl_b B
on A.col_1 = B.col_1
and A.col_2 = B.col_2
left join
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
on
C.col_2 = A.col_2
As a guess. I'm not entirely sure what your join conditions should be but that's my first attempt.
This is expected behaviour. When you join two result sets, you only want to get results where the join criteria is satisfied. If the criteria are not satisfied, you should get no results.
If I run the query "get me all the employees older than 65, and get their departments", if there are no employees older than 65, you would not expect to get any results, even if there are some departments in the database.
SELECT emp.name, dept.dept_name
FROM emp
JOIN dept
ON (emp.dept_no = dept.dept_no)
WHERE emp.age > 65;
As the others said, if you actually want to get rows regardless of whether the subquery has any results, you need to use an outer join.

Oracle: column ambiguously defined

I know there are lots of questions like these, but my question is not how to get rid of this error but to know how this worked earlier in 9-th version of Oracle.
I've got an old sources written in Ruby and Oracle DB which recently was upgraded to version=11.
I cannot edit data in Oracle DB, only read. so there are two tables lets say: table A(id, name, type, customer) and table B(id,a_id,type,person)
so. there is a query in the source code:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
so in Oracle 9 this worked perfectly but now i've got "column ambiguously defined" error.
What i'd like to know is:
where type = 'A'
is the same as
where a.type = 'A' AND b.type = 'A'
or
where a.type = 'A' OR b.type = 'A'
?
I think this was a bug with the ANSI style join. Use DBMS_XPLAN to find which table was being filtered in the old database.
Or better still, work out from the business logic what they query SHOULD have been.
No, and that's the problem: It could mean
where a.type = 'A'
or it could mean
where b.type = 'A'
with potentially different results; hence the error saying it is ambiguously defined.
I think you should test in Oracle 9 (where you say it works) and compare the output of the ambiguous query:
--- Base
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
with both the non-ambiguous ones:
--- QueryA
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
and:
--- QueryB
select a.id,b.id from a join b on a.id = b.a_id where b.type = 'A'
Something like this would do:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
MINUS
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
(in short):
(Base)
MINUS
(QueryA)
and then:
(QueryA)
MINUS
(Base)
If both of the above MINUS queries return 0 rows, then BASE query is interpreted as QueryA.
Check similarly and compare Base with QueryB.
Another plausible reason for this error is that during (or about the same period with ) the migration, a type column was added in the 2nd table. Do you have old versions of the database tables' definitions to check that?
All - keep in mind there was a major change to the optimization engine for 11g. If you set your query optimizer level to 10.2.x on your 11g instance I bet the query would start working again.
That being said you should provide the alias for it so it's not ambiguous to the database server or the DBA / Developer coming behind you. :)

Resources