Negate a bind variable - sql

I am using APEX 5.0 and I have a query such as:
Select * FROM table where condition = :BIND_VARIABLE
I have a list which dynamically fills in the bind variable. The list has two values which the bind variable can take:
Value 1
Everything except value 1
'Everything else' value which is returned is user controlled so I can't have an EXISTS or IN because I do not know all the values that will be in there.
Is it possible to do something like
Select * FROM table where condition = !'Value 1'

I don't remember exact syntax for oracle substring, but you can try something like:
Select *
FROM table
where
(condition = :BIND_VARIABLE AND SUBSTR(:BIND_VARIABLE, 1, 1) <> '!')
OR
(condition <> SUBSTR(:BIND_VARIABLE, 2) AND SUBSTR(:BIND_VARIABLE, 1, 1) = '!')
so, if your value starts with ! symbol - you will look for all except passed value

Related

Check if the first or second condition exists

I have a little problem selecting queries, namely when I want to check the first condition with the code below
select * from VL_Faktura_Queue where FAK_KundenNr=127849 AND (FAK_BoMatNr LIKE '%verk%' AND FAK_VerrechnetBis ='0001-01-01')
, it shows me one position, but when I add a condition where I want to check if there is a FAK_KundenNr with FAK_BomatNr LIKE '% Verk%' OR FAK_BoMatNr Like 'Zus%' also throws me different values that do not fall under FAK_KundenNr = 127849, as I can easily check that it returns my values for this KundenNr, where there is 1 OR 2 condition.
this is my query:
select * from VL_Faktura_Queue where FAK_KundenNr=127849
AND (FAK_BoMatNr LIKE '%verk%' AND FAK_VerrechnetBis ='0001-01-01') --this would be the first condition
or FAK_BoMatNr like 'Zus%' --and this the second condition
This is the individual selection I should get but in one query at the end
so my question is how can i get in one query select from these two query from the picture, thanks everyone for the help
Your parentheses are not sufficient. AND has precedence over OR, so you have FAK_KundenNr = 127849 AND (<first condition)> OR FAK_BoMatNr like 'Zus%'.
SELECT *
FROM VL_Faktura_Queue
WHERE FAK_KundenNr = 127849
AND
(
(FAK_BoMatNr LIKE '%verk%' AND FAK_VerrechnetBis = '0001-01-01')
or
FAK_BoMatNr LIKE 'Zus%'
);
In your requirement, you need to combine the "AND" operator with other logical "OR" operator.
SELECT *
FROM VL_Faktura_Queue
WHERE
(
( FAK_BoMatNr LIKE '%verk%'
AND FAK_VerrechnetBis = '0001-01-01'
) -- 1st Condition
or
(FAK_BoMatNr LIKE 'Zus%') -- 2nd Condition
)
AND FAK_KundenNr = 127849;
Please check if this solution is working for you.

Check if any substring from array appear in string?

I have the following query:
select case when count(*)>0 then true else false end
from tab
where param in ('a','b') and position('T' in listofitem)>0
This checks if 'T' exists in the column listofitem and if it does the count is > 0. Basically it's a search for sub string.
This works well in this private case. However my real case is that I have text[] called sub_array meaning multiple values to check. How can I modify the query to handle the sub_array type? I prefer to have it in a query rather than a function with a LOOP.
What I actualy need is:
select case when count(*)>0 then true else false end
from tab
where param in ('a','b') and position(sub_array in listofitem)>0
This is not working since sub_array is of type Text[]
Use the unnest() function to expand your array & bool_and() (or bool_or() -- this depends on what you want match: all array elements, or at least one) to aggregate:
select count(*) > 0
from tab
where param in ('a','b')
and (select bool_and(position(u in listofitem) > 0)
from unnest(sub_array) u)
A brute force method would be to convert the array to a string:
select (count(*) > 0) as flag
from tab
where param in ('a','b') and
array_to_string(listofitem, '') like '%T%';
I should note that comparing count(*) is not the most efficient way of doing this. I would suggest instead:
select exists (select 1
from tab
where param in ('a','b') and
array_to_string(listofitem, '') like '%T%'
) as flag;
This stops the logic at the first match, rather than counting all matching rows.

Select Where Like regular expression

I need to create a SQL Query.
This query need to select from a table where a column contains regular expression.
For example, I have those values:
TABLE test (name)
XHRTCNW
DHRTRRR
XHRTCOP
CPHCTPC
CDDHRTF
PEOFOFD
I want to select all the data who have "HRT" after 1 char (value 1, 2 and 3 - Values who looks like "-HRT---") but not those who might have "HRT" after 1 char (value 5).
So I'm not sure how to do it because a simple
SELECT *
FROM test
WHERE name LIKE "%HRT%"
will return value 1, 2, 3 and 5.
Sorry if I'm not really clear with what I want/need.
You can also change the pattern. Instead of using % which means zero-or-more anything, you can use _ which means exactly one.
SELECT * FROM test WHERE name like '_HRT%';
You can use substring.
SELECT * FROM test WHERE substring(name from 2 for 3) = 'HRT'
Are the names always 7 letters? Do:
SELECT substring (2, 4, field) from sometable
That will just select the 2-4th characters and then you can use like "%HRT"

sql in clause doesn't work

I have a table with a column ancestry holding a list of ancestors formatted like this "1/12/45". 1 is the root, 12 is children of 1, etc...
I need to find all the records having a specific node/number in their ancestry list. To do so, I wrote this sql statement:
select * from nodes where 1 in (nodes.ancestry)
I get following error statement: operator does not exist: integer = text
I tried this as well:
select * from nodes where '1' in (nodes.ancestry)
but it only returns the records having 1 in their ancestry field. Not the one having for instance 1/12/45
What's wrong?
Thanks!
This sounds like a job for LIKE, not IN.
If we assume you want to search for this value in any position, and then we might try:
select * from nodes where '/' + nodes.ancestry + '/' like '%/1/%'
Note that exact syntax for string concatenation varies between SQL products. Note that I'm prepending and appending to the ancestry column so that we don't have to treat the first/last items in the list differently than middle items. Note also that we surround the 1 with /s, so that we don't get false matches for e.g. with /51/ or /12/.
In MySQL you could write:
SELECT * FROM nodes
WHERE ancestry = '1'
OR LEFT(ancestry, 2) = '1/'
OR RIGHT(ancestry, 2) = '/1'
OR INSTR(ancestry, '/1/') > 0
The in operator expects a comma separated list of values, or a query result, i.e.:
... in (1,2,3,4,5)
or:
... in (select id from SomeOtherTable)
What you need to do is to create a string from the number, so that you can look for it in the other string.
Just looking for the string '1' in the ancestry list would give false positives, as it would find it in the string '2/12/45'. You need to add the separator to the beginning and the end of both strings, so that you look for a string like '/1/' in a string like '/1/12/45/':
select * from nodes
where charindex('/' + convert(varchar(50), 1) + '/', '/' + nodes.ancestry + '/') <> 0

T-SQL Case statement utilizing substring and isnumeric

I have a T-SQL stored proc that supplies a good amount of data to a grid on a .NET page....so much so that I put choices at the top of the page for "0-9" and each letter in the alphabet so that when the user clicks the letter I want to filter my results based on results that begin with that first letter. Let's say we're using product names. So if the user clicks on "A" I only want my stored proc to return results where SUBSTRING(ProductName, 1, 1) = "A".
Where I'm getting hung up is on product names that begin with a number. In that case I want to fetch all ProductName values where ISNUMERIC(SUBSTRING(ProductName, 1, 1)) = 1. I'm using an input parameter called #FL. #FL will either be a zero (we have few products that begin with numerics, so I lump them all together this way).
Of course there's also the alternative of WHERE SUBSTRING(ProductName, 1, 1) IN ('0', '1', '2'.....) but even then, I've never been able to devise a CASE statement that will do an = on one evaluation and an IN statement for the other.
Here's what I have in my proc for the CASE part of my WHERE clause. It doesn't work, but it may be valuable if only from a pseudocode standpoint.
Thanks in advance for any ideas you may have.
AND CASE #FL
WHEN "0" THEN
CASE WHEN #FL = "0" THEN
isnumeric(substring(dbo.AssnCtrl.Name, 1, 1)) = 1
ELSE
SUBSTRING(dbo.AssnCtrl.Name, 1, 1) = #FL
END
END
*** I know that this use of the CASE statement is "non-standard", but I found it online and thought it had some promise. But attempts to use a single CASE statement yielded the same result (an error near '=').
Why not just use Like operator ?
Where dbo.AssnCtrl.Name Like #FL + '%'
When they select the Any Number option, pass in #FL as '[0-9]'
(I assume you have an index on this name column ?)
To steal a bit from Charles:
AND Substring(dbo.AssnCtrl.Name, 1, 1) Like
CASE WHEN #FL = '0' THEN '[0-9]'
ELSE #FL
END
Have you tried
AND (
isnumeric(substring(dbo.AssnCtrl.Name, 1, 1)) = 1
or
SUBSTRING(dbo.AssnCtrl.Name, 1, 1) = #FL )
this works for me:
select * from casefile where
isnumeric(substring(pmin,1,1)) = 1
or
substring(pmin,1,1) = 'a'