Optimizing Doctrine WHERE Clause with Regex - doctrine

See the Below Doctrine Query:
SELECT values, orgunit, form
FROM Values values
INNER JOIN values.orgunit orgunit
INNER JOIN values.form form
INNER JOIN orgunit.orgunitStructure orgunitStructure
WHERE orgunitStructure.level1Id=123032
AND orgunitStructure.level >= (SELECT selectedOrgSructure.level FROM OrgunitStructure selectedOrgSructure WHERE selectedOrgSructure.orgunit=123032 )
AND form.id IN(189,187,190,188)
AND (
LOWER(values.value) LIKE '%"189886":"10369434"%'
OR LOWER(values.value) LIKE '%"189880":"10369434"%'
OR LOWER(values.value) LIKE '%"189881":"10369434"%'
OR LOWER(values.value) LIKE '%"189871":"10369434"%'
OR LOWER(values.value) LIKE '%"189888":"10369434"%'
OR LOWER(values.value) LIKE '%"189873":"10369434"%'
OR LOWER(values.value) LIKE '%"189870":"10369434"%'
OR LOWER(values.value) LIKE '%"189863":"10369434"%'
OR LOWER(values.value) LIKE '%"189865":"10369434"%'
OR LOWER(values.value) LIKE '%"189867":"10369434"%'
OR LOWER(values.value) LIKE '%"189869":"10369434"%'
OR LOWER(values.value) LIKE '%"189872":"10369434"%'
OR LOWER(values.value) LIKE '%"189894":"10369434"%'
OR LOWER(values.value) LIKE '%"189896":"10369434"%'
OR LOWER(orgunit.longname) LIKE '%10369434%'
)
I'm looking for REGEX Optimization of the WHERE clause, specifically putting the ORs together into something like, from:
LOWER(values.value) LIKE '%"189886":"10369434"%'
OR LOWER(values.value) LIKE '%"189880":"10369434"%'
OR LOWER(values.value) LIKE '%"189881":"10369434"%'
OR LOWER(values.value) LIKE '%"189871":"10369434"%'
OR LOWER(values.value) LIKE '%"189888":"10369434"%'
OR LOWER(values.value) LIKE '%"189873":"10369434"%'
OR LOWER(values.value) LIKE '%"189870":"10369434"%'
Into:
LOWER(values.value) REGEXP '%("189886":"10369434")|("189886":"10369434")|("189880":"10369434")|("189881":"10369434")|("189871":"10369434")|("189888":"10369434")|("189873":"10369434")%'

Related

WILDCARDS in SQL Oracle [duplicate]

This question already has answers here:
Can't we use [specifier] with like operator with Oracle?
(1 answer)
Query the list of CITY names starting with vowels (i.e., a, e, i, o, or u) from STATION
(18 answers)
Closed 3 years ago.
I am trying to find all the name that starts with either A,B or C in Oracle DB and I wrote this syntax:
SELECT NUME FROM JUCATORI
WHERE NUME LIKE '[ABC]%';
but it doesn't not give me any name (neither error), even though I am sure I have in my DB names that starts with either A,B or C.
LIKE doesn't work with character sets. (I think T-SQL extended LIKE to deal with such expressions, but Oracle's SQL doesn't.) You don't get an error, because LIKE '[ABC]%' looks for strings starting with an opening bracket, followed by an A, then a B, then a C, then a closing bracket
So either use OR:
SELECT nume FROM jucatori WHERE nume LIKE 'A%' OR nume LIKE 'B%' OR nume LIKE 'C%';
Or a regular expression:
SELECT nume FROM jucatori WHERE REGEXP_LIKE(nume, '^[ABC]');
One option is
where substr(nume, 1, 1) in ('A', 'B', 'C')
You're confusing regular expressions with 'like' conditions.
Like checks for exactly the string you pass to it, with the only three exceptions being:
1. % - any number of any characters
2. _ - any single character
3. ESCAPE clause that lets you define escape character
so you can use % as 'I'm looking for percent sign'
[ABC] meaning 'either A, B or C' is a regular expression syntax.
You may want to use regexp_like instead, or for such simple query just 'OR' several likes:
with examples as (
select 'Adam' ex from dual union all
select 'Dorothy' ex from dual union all
select '[ABC]something' ex from dual union all
select '[ABC]' from dual
)
select e.ex,
case when e.ex like '[ABC]%' then 'MATCHES' else null end as matches_like,
case when regexp_like(e.ex, '^[ABC].?') then 'MATCHES' else null end as matches_regexp_like,
case when e.ex like 'A%' or e.ex like 'B%' or e.ex like 'C%' then 'MATCHES' else null end as matches_complex_like
from examples e

LIKE operator is not fetching results in oracle

I want to get the results by applying LIKE operator. But its not giving me the result.
Below is my Query.
Select * from TBL_ZONAL_HEAD_INFO where upper(ZONE_HEAD_NAME) LIKE '%ami%';
The above query is not fetching me any results from the data below
Query in procedure
Select * from TBL_ZONAL_HEAD_INFO where upper(ZONE_HEAD_NAME) LIKE '%' || upper(P_ZONENAME) || '%';
upper(ZONE_HEAD_NAME) is all uppercase, so it will never be LIKE '%ami%' (which is all lowercase).
You have to match it with UPPER CASE.
SELECT
*
FROM
TBL_ZONAL_HEAD_INFO
WHERE
UPPER(ZONE_HEAD_NAME) LIKE upper('%Ami%'); -- used upper case AMI here
Cheers!!
Use LOWER not UPPER:
Select * from TBL_ZONAL_HEAD_INFO where LOWER(ZONE_HEAD_NAME) LIKE '%ami%';
or use upper case in the LIKE:
Select * from TBL_ZONAL_HEAD_INFO where UPPER(ZONE_HEAD_NAME) LIKE '%AMI%';
or wrap both sides of the LIKE in the same case-transforming function:
Select * from TBL_ZONAL_HEAD_INFO where UPPER(ZONE_HEAD_NAME) LIKE UPPER('%Ami%');
try this :
Select * from TBL_ZONAL_HEAD_INFO where upper(ZONE_HEAD_NAME) LIKE upper('%ami%');
You have used upper for ZONE_HEAD_NAME and used '%ami%' which won't ever return any records, ever.
So, either make both in upper() function, or just use Uppercase for select query here, like '%AMI%'.

PL/SQL Stored proc that uses a comma separated parameter to drive a dynamic LIKE clause?

Is there a fairly simple way to take an input parameter containing a comma seperated list of prefixes and return a cursor based on a select statement that uses these?
i.e. (Pseudocode)
PROCEDURE get_by_prefix(p_list_of_prefixes IN varchar2, r_csr OUT SYS_REFCURSOR)
IS
BEGIN
OPEN r_csr FOR
SELECT * FROM my_table where some_column LIKE (the_individual_fields_from p_list_of_prefixes ||'%')
END
I've tried various combinations, and now have two problems - coercing the input into a suitable table (I think it needs to go into a table type rather than a VARCHAR2_TABLE), and secondly getting the like clause to be effectively a SELECT from an internal 'pseudotable'...
EDIT: It seems that people are suggesting ways to use 'IN' with a set of potential values - whereas Im looking at using LIKE. I could use a similar technique - building up dynamic SQL, but was wondering if there isnt a more elegant way...
PL/SQL has no concept of a comma-separated list and no built-in splitter as in Perl etc, so you'll have to use one of the hand-rolled methods such as this one:
https://stewashton.wordpress.com/2016/08/01/splitting-strings-surprise
(Other methods are available.) Then it's just a matter of either populating a collection in one step and using it in the next, or else combining the two as something like this:
declare
p_list_of_prefixes varchar2(100) := 'John,Jim,Jules,Janice,Jenny';
begin
open :refcur for
with params as
( select x.firstname
from xmltable(
'ora:tokenize($X, "\,")'
passing p_list_of_prefixes as x
columns firstname varchar2(4000) path '.'
) x
)
, people as
( select 'Dave Clark' as fullname from dual union all
select 'Jim Potter' from dual union all
select 'Jenny Jones' from dual
)
select x.firstname, p.fullname
from params x
left join people p on p.fullname like x.firstname || '%';
end;
Output:
FIRSTNAME FULLNAME
-------------- -----------
John
Jim Jim Potter
Jules
Janice
Jenny Jenny Jones
Using LIKE the way you want is easy, but it is the wrong solution. (See my Comment under the original post).
Anyway - if by order of your superiors, or some other semi-legitimate reason, you must use a LIKE condition, it should look something like this:
... where ',' || p_list_of_whatever || ',' like '%,' || some_column || ',%
Concatenating commas at both ends of both sides of the comparison is needed, because you don't want Jo in the column to match John in the input list. Start from there and you will see why you need the commas on the right-hand side, and then follow from there and you will see why you need them on the left also.

How do I run a general SQL LIKE statement with specific exclusions?

I am writing a query in MS Access¹ towards an Oracle database, where I am trying to find everyone incarcerated in prisons in Norway during the census of 1875. To do this, I have to search for keywords in several different fields, as the ennumerators would describe their state several different ways, e.g.:
By describing their family connection as ‘Fange’, ‘Arrestant’ (prisoner) or the likes.
By listing them as temporarily present at a location named ‘Fængsel’ (prison) or the likes.
If at their family’s home, by listing them as absent and naming their assumed location as above.
By listing them as living in a separate building, named ‘Fængsel’ or the likes.
By listing their profession as ‘Fange’, ‘Arrestant’ (v.s.) or the likes.
One of the keywords I am looking for, is variants of ‘Bodsfængsel’ (a ‘prison of penitence’). Problems is, ‘Bod’ can also mean stall/small building. To make sure I include all variants of ‘Bodsfængsel’, I have written the following lines (only the relevant code snippet is shown here; a complete section is shown below):
Or BOSTNVN Like "*bod*"
And
(
BOSTNVN not Like "*bode*" or
BOSTNVN not Like "*dbod*" or
BOSTNVN not Like "*bodg*"
)
Problem is, when I run this code, I get 8513 hits, exactly the same number of lines as when I exclude the not like-lines.
Comments:
The exclusions are to avoid hits on placenames such as ‘Toldbod’, ‘Boden’ or ‘Toldbodgade’
If I somehow could get it to output extra fields (e.g. Field0, Field1, Field2 et c.) to show where the hit was found, it would probably make it much easier to find the errors too.
I hope I have provided all necessary information. Please don’t chop my head off!
¹ Access 2007 on Win 7 Enterprise.
Here is a complete snippet from the beginning of the query; if this is not necessary, please advise, and I will remove it:
SELECT
KOMMNR, KRETSNR, BOSTNR, PERSNR,
⋮
PID
FROM
FOLKETELLINGER_PERSON_1875
WHERE
(
(
KOMMNR Not Like "11*"
And KOMMNR Not Like "12*"
⋮
And KOMMNR Not Like "17*"
)
AND (
SEDVBO Like "*Fæng*"
Or SEDVBO Like "*fæng*"
⋮
Or SEDVBO Like "*arest*"
And
(
SEDVBO not Like "*Bode*" or
SEDVBO not Like "*dBod*" or
SEDVBO not Like "*Bodg*"
)
Or SEDVBO Like "*bod*"
And
(
SEDVBO not Like "*bode*" or
SEDVBO not Like "*dbod*" or
SEDVBO not Like "*bodg*"
)
Or SEDVBO Like "*Bot*"
And
(
SEDVBO not Like "*Bote*" or
SEDVBO not Like "*dBot*" or
SEDVBO not Like "*Botg*"
)
Or SEDVBO Like "*bot*"
And
(
SEDVBO not Like "*bote*" or
SEDVBO not Like "*dbot*" or
SEDVBO not Like "*botg*"
)
)
)
OR (
⋮
);
First, SQL is not case sensitive, so you have redundant lines. E.g. these two do the same thing:
Or SEDVBO Like "*Bot*"
Or SEDVBO Like "*bot*"
You're using or in your bottom level conditions where you should be using and. If you use or it will return all records because if any one of the inclusion criteria are triggered the record would be included even if it fails all others at that same level. For example, if a value is not Like '*Bode*' it will be included even if it is like "*dBod*".
You also have your code split out in a more complex manner than necessary, if the code is meant to have the statements at the level they currently are. You can condense your SEDVBO block like this:
SEDVBO Like "*arest*"
Or SEDVBO Like "*bod*"
Or SEDVBO Like "*Bot*"
And
(
SEDVBO not Like "*Bode*" and
SEDVBO not Like "*dBod*" and
SEDVBO not Like "*Bodg*" and
SEDVBO not Like "*bote*" and
SEDVBO not Like "*dbot*" and
SEDVBO not Like "*botg*"
)
Or if you're trying to do what I think you might be, namely looking for unique combinations of Like and not Like you are missing parentheses around each or/and pairing. You'd add them like this:
(SEDVBO Like "*arest*"
And
(
SEDVBO not Like "*Bode*" and
SEDVBO not Like "*dBod*" and
SEDVBO not Like "*Bodg*"
)
)
Or
(SEDVBO Like "*bod*"
And
(
SEDVBO not Like "*bode*" and
SEDVBO not Like "*dbod*" and
SEDVBO not Like "*bodg*"
)
)
Or
(SEDVBO Like "*bot*"
And
(
SEDVBO not Like "*bote*" and
SEDVBO not Like "*dbot*" and
SEDVBO not Like "*botg*"
)
)
Your first snippet would become:
Or
(BOSTNVN Like "*bod*"
And
(
BOSTNVN not Like "*bode*" and
BOSTNVN not Like "*dbod*" and
BOSTNVN not Like "*bodg*"
)
)

Oracle PL/SQL Select into variable using WITH clause

I have a WITH clause that gives me the desired result, and i'm trying to put it in a variable. I have omitted code for simplicity. The last line of code is most relevant.
WITH ALL_VE_ERRORS AS (
SELECT *
FROM ASN.AN_VALIDATION_ERRORS
WHERE ...
), FILTER_STATUS AS (
SELECT *
FROM ALL_VE_ERRORS
WHERE ...
) SELECT UNIT_DISCREPANCY FROM FILTER_STATUS INTO W_UNIT_DISCREPANCY; <-- like this
But this doesn't work, the compiler doesn't like this. I also tried putting it first like this:
SELECT INTO W_UNIT_DISCREPANCY <-- or like this
WITH ALL_VE_ERRORS AS (...
Anyone know the proper syntax to do something like this?
If you have no reasons I can't see, you don't need two tables in your WITH clause; you could simplify it this way:
WITH ALL_VE_ERRORS AS (
SELECT *
FROM ASN.AN_VALIDATION_ERRORS
WHERE ...
)
SELECT UNIT_DISCREPANCY
INTO W_UNIT_DISCREPANCY
FROM ALL_VE_ERRORS
WHERE ...
Otherwise, you can use:
WITH ALL_VE_ERRORS AS (
SELECT *
FROM ASN.AN_VALIDATION_ERRORS
WHERE ...
), FILTER_STATUS AS (
SELECT *
FROM ALL_VE_ERRORS
WHERE ...
)
SELECT UNIT_DISCREPANCY
INTO W_UNIT_DISCREPANCY
FROM FILTER_STATUS

Resources