Check if any substring from array appear in string? - sql

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.

Related

How to use Decode Function in the case where column has string values

I have a view xxabc_v (shown below), I need to update the "Code" column to Null wherever it is N/A when "Value" column sum (900+(-900)=0) becomes zero for the "field_name" values (Demand A+Demand B) for the "Date" 01-Apr-21.
How can I put the decode logic to code column in the above case?
Table structure and expected output:
You don't want decode() because a much simpler method works:
select nullif(code, 'N/A')
This returns NULL when code takes on the specified value.
If you actually want to change the data, then you want update:
update t
set code = NULL
where code = 'N/A';
EDIT:
I see, you have an extra condition. So, use case:
(case when code = 'N/A' and
sum(value) over (partition by id, date) = 0
then NULL
else code
end)
I assumed that you need date wise id wise sum when to sum(). Please check this out:
select date,id,(case when sum(value)over(partition by date,id)=0 and code='N/A' then NULL
else Code end)code, field_name,value
from tablename

If-Then Statement In A SQL Query Insists On Trying To Convert To Wrong Type, Then Fails

I have a SQL query, linking table 1 to table 2 via an inner join, containing this part in the select part of the statement:
select
table1.field1,
table2.field1,
CASE (table2.field1)
WHEN -2 THEN ''
ELSE table2.field2
END as table2Field2,
table3.field4
from...
I want to be able to return table2Field2 when it has a relevant value, ie: when the object represented in table2 is not null, so that table2.field1 does not have a value of -2. In this case, the value of table2Field2 should be blank instead of a meaningless value.
However, this returns 0 instead of the blank text. If I change this line:
WHEN -2 THEN ''
to this:
WHEN -2 THEN 'someText'
then it complains at me that it's trying to convert an int to a string, which I'm not. table2field1 is an int, but table2Field2 is a string, which is what we're actually returning here.
How do I state (even more specifically) in this query that I'm returning the string field as a string, and not something else as a string that isn't (a) a string, and (b) the thing I specified I'm returning please?
All suggestions welcome, many thanks in advance for any help :)
In a CASE expression, all of the possible return values must be of the same data type. As written, the expression is trying to return one string and one integer.
If you want an empty string for your first output, you can CAST or CONVERT your second output to a character type value:
select
table1.field1,
table2.field1,
CASE (table2.field1)
WHEN -2 THEN ''
ELSE CAST(table2.field2 AS varchar(12)) --< 12 will cover any value of integer.
END as table2Field2,
table3.field4
from...
Is it possible you have your as table2field2 in the wrong location?
maybe try:
select
table1.field1,
table2.field1,
CASE (table2.field1)
WHEN -2 THEN ''
ELSE table2.field2
END as table2Field2,
table3.field4
from...
Because you do not want to answer me what is the database you use then I have to do it like this hehehe:
SQL Server: DEMO
select
t.col1,
CASE
WHEN convert(char,t.col1) = '-2' THEN 'aaa'
ELSE convert(char,(t.col2))
END test
from Tab1 t;
Oracle DEMO
select
t.col1,
CASE
WHEN to_char(t.col1) = '-2' THEN 'aaa'
ELSE to_char(t.col2)
END test
from tab1 t;

return more than one row as comma separated values from case when statement

Trying to create a function in Postgresql with 4 arguments that returns a table(multiple rows).
Arguments: in_customer_id, in_start_date, in_end_date, in_risk_flag
The sql query I am using in that function is:
select * from customer as k
where k.customer_id IN (case when $1 = 0 then (select distinct(customer_id) from customer)
when $1 != 0 then $1
end)
and k.start_date >= $2
and k.end_date <= $3
and k.risk_flag IN (case when $4 = 0 then (select distinct(risk_flag) from customer)
when $4 != 0 then $4
end)
Error I am getting is error [21000]: more than one row returned by subquery used as an expression.
Is there any way to get return from case statement as (1,2,3,4,5,6) (comma separated values) instead of a column with multiple rows?
First: distinct is not a function. Writing distinct (customer_id) makes no sense. And in a sub-select that's used for an IN condition the distinct is useless anyway.
It seems that you want to select a specific customer in case you pass a parameter, otherwise you want to select all of them. As far as I can tell, you don't need a sub-select for that. Something like that should do it:
where k.customer_id = case
when $1 <> 0 then $1
else k.customer_id
end
It essentially turns the condition to where customer_id = customer_id when the first parameter is passed as 0 (although you should better use a null value for that, rather then a "magic" value like zero)
This assumes that customer_id is defined as NOT NULL otherwise this will not work.
You can apply the same pattern for risk_id (again: it will only work if risk_id can not contain NULL values).
This logic is usually simplified to avoid the case in the where clause:
where ($1 = 0 or $1 = k.customer_id) and
. . .

Return 'Yes' or No' from select statement?

tbl_LoanSummary has Sample_Number column. I have to check if Sample_Number column is not null the return 'Y' otherwise return return 'N' from below select statement.
select a.Br_Loan_No ,a.Br_LookupKey, //return IsNull(s.Sample_Number) ='N' or 'Y'
from dbo.tbl_Br a left outer join dbo.tbl_LoanSummary s
on s.Loan_no = a.Br_Loan_No order by a.Br_Loan_No
How to do this?
You can use the case expression for this...
select a.Br_Loan_No,
a.Br_LookupKey,
CASE WHEN s.Sample_Number IS NULL THEN 'N' ELSE 'Y' END AS [HasSample]
from dbo.tbl_Br a left outer join dbo.tbl_LoanSummary s
on s.Loan_no = a.Br_Loan_No order by a.Br_Loan_No
In Oracle, you could also use
select NVL(s.Sample_Number, 'N')
to return N in case of null value
(of course you still need something to have Y in case of not null.)
You'll want to use a CASE expression. It's like an embedded if-statement or switch-statement from traditional programming languages.
SELECT a.Br_Loan_No,
a.Br_LookupKey
CASE
WHEN s.Sample_Number IS NULL THEN 'N'
ELSE 'Y'
END AS sample_number_is_not_null
FROM dbo.tbl_Br a
LEFT JOIN dbo.tbl_LoanSummary s
ON s.Loan_no = a.Br_Loan_No
ORDER BY a.Br_Loan_no
Note that you are creating a computed column here, rather than selecting the raw value of an existing column. It's generally required that you give this column a name, thus the use of the AS sample_number_is_not_null.
There are two forms of the CASE expression. One lets you compare a column or value against several choices. It is like using an implicit equals:
CASE foo
WHEN 3 THEN 'foo is 3!'
WHEN 4 THEN 'foo is 4!'
ELSE 'foo is not 3 or 4'
END
The other form, in the example at the top, lets you use arbitrary expressions in each WHEN clause. It should be noted that each WHEN clause is evaluated in order and the first one to match is the one whose THEN is used as the result. If none of the WHENs match, then the result in the ELSE is used.

SQLServer - Select bool if column begins with a string

I would like to select a boolean of whether or not a column begins with a certain string.
SELECT (name LIKE 'foo%') AS isFoo FROM bar;
Is there a way to do this without using an inline CASE?
No
There is neither implicit boolean CAST in SQL Server nor a boolean type
SELECT CAST(CASE WHEN name LIKE 'foo%' THEN 1 ELSE 0 END AS bit) AS isFoo
FROM bar;
You might not even need the cast depending on your usage:
SELECT CAST(PATINDEX('foo%'), name) AS bit) FROM bar
This will return 1 if the col starts with the text otherwise 0. No CASE involved.
A UNION operation would let you skip a CASE statement by combining two result sets. In the first query you filter for all rows that match 'foo%' and in the second you match all rows that do not match 'foo%'
Something like:
SELECT 1 AS [YourBoolean], 'fool' WHERE 'fool' LIKE 'foo%'
UNION
SELECT 0, 'fuel' WHERE 'fuel' NOT LIKE 'foo%'
ORDER BY 1
(Hard-coded example w/o target table.)
Create a User Defined function that you can call inorder to check if the name contains foo.
Not to take away from what gbn suggested but I think this would be more efficient (but essentially the same thing)
SELECT CAST(CASE WHEN LEFT(name, 3)='foo' THEN 1 ELSE 0 END AS bit) AS isFoo
FROM bar;
SELECT
CASE WHEN name LIKE 'foo%'
THEN 1
ELSE 0
END as isFoo
FROM bar