Combine IN and LIKE function in DB2 - db2

Is there a way to combine IN and LIKE function together in DB2? For example I would like to exclude users that have userid A,B,C and also userid that start from X% or Y% . I tried the below query however it did not work
select * from table where userid not in ('A','B','C') or (not like 'X%' or not like 'Y%')

Use 'AND' instead of 'OR'
select * from table
where userid not in ('A','B','C')
and userid not like 'X%'
and userid not like 'Y%'

You may use all the constants used in IN in LIKE:
with
table (userid) as
(
values 'A', 'AA', 'XX', 'YY', 'ZZ'
)
, vals (userid) as
(
values 'A', 'B', 'C', 'X%', 'Y%'
)
select *
from table t
where not exists
(
select 1
from vals v
where t.userid like v.userid
);
The result is:
|USERID|
|------|
|AA |
|ZZ |

Related

Operator equivalent to 'includes'

I'm trying to JOIN a bunch of tables and I'm new to Postgres and Knex.
Is there an equivalent to the javascript operator 'includes'? e.g. I want to do something like this:
JOIN tbl ON somearrayofIds 'includes' tbl.id
Here's my fetch query:
db('posts AS p')
.select(
'p.id as postId',
'p.user_id as pUserId',
'p.content',
'p.created_at',
'p.updated_at',
'p.image_url as postImage',
'pr.post_id as prPostId',
'pr.reaction_ids as prReactionIds',
'pr.user_ids as prUserIds',
'r.id as rId',
'r.keyword as rKeyword',
)
.leftJoin('post_reactions AS pr', 'pr.post_id', '=', 'p.id')
.leftJoin('reactions AS r', 'r.id', 'includes', 'pr.reaction_ids') // r.id is string, pr.reaction_ids is array
Something like this?:
create table array_test(id int, array_fld int[]);
insert into array_test values (1, '{1, 3, 5}');
select * from array_test where 1 = ANY(array_fld);
id | array_fld
----+-----------
1 | {1,3,5}
select * from array_test where 2 = ANY(array_fld);
id | array_fld
----+-----------
(0 rows)

Retrieve rows with a column value that do not exist in a given list

Let's say I have a list of values
'A', 'B', 'C','D','E',...,'X'.
And I have a database column CHARS that is storing the exact values of my list (one value / row) except for 'C' and 'E'. So, CHARS contains 'A', 'B', 'D',..., 'X'.
Is there a way in PostgreSQL to return only the rows for 'C' and 'E'; the values from my list which are missing from column CHARS?
If your list of values come from outside of the database (e.g. a program), the simplest solution should be the NOT INoperator
SELECT * FROM your_table WHERE chars NOT IN ('A', 'B', 'C', 'D', 'E', ..., 'X')
(Note: The missing characters in the tuple can't be abbreviated with .... So you have write them all.)
If your list of values come from a table or query, you can use a subquery:
SELECT * FROM your_table WHERE chars NOT IN (SELECT a_char FROM another_table WHERE ...);
You can do an outer join against a values clause:
select i.ch as missing_character
from (
values
('A'), ('B'), ('C'), ('D'), ('E'), ('F'), ..., ('X')
) as i(ch)
left join the_table t on i.ch = t.chars
where t.chars is null
order by i.ch;
Note that each char needs to be enclosed in parentheses in the values clause to make sure that each one is a single row.
Alternatively you can use the EXCEPT operator:
select ch
from (
values ('A'), ('B'), ('C'), ('D'), ('E'), ('F'), ... , ('X')
) as i(ch)
except
select chars
from the_table
order by ch
Online example: https://rextester.com/XOUB52627

Fuzzy string search in array with postgresql

This is how I do fuzzy string search in postgresql:
select * from table where levenshtein(name, 'value') < 2;
But what can I do if the 'name' colum contains array?
P.S.: It is necessary to use index. And this is the difference.
You can use unnest() over the array:
select * from
(
select unnest(name) as name_in_array, id from
(
select 1 as id, ARRAY['value1','valu','lav'] as name
union all
select 2 as id, ARRAY['value2','orange','yellow'] as name
)t1
) t2
where levenshtein(name_in_array, 'value') < 2;

Nesting and using LIKE and OR in postgres

I'm trying to nest this query, but I am getting the error: invalid input syntax for type boolean: "%malfunction%".
select *
from (
select column_one, column_two
from table
group by column_one, column_two
) as new_table
where column_two like '%false%' or '%malfunction%' or '%accidental%' or '%mistaken%'
order by column_one
Column_two is not boolean but it's identifying it as one.
I feel like I'm missing something small, but I can't find it. Help!
You can use any(array[...]), example:
with test (col) as (
values
('pear'), ('banana'), ('apple')
)
select *
from test
where col like any(array['%ea%', '%ba%']);
col
--------
pear
banana
(2 rows)
Correct syntax is something like select col1, col2,
from table_name
where condition1 OR condition2 OR condition3 ...;

How to count the frequency of integers in a set of querystrings in postgres

I have a column in a postgres database which logs search querystrings for a page on our website.
The column contains data like
"a=2&b=4"
"a=2,3"
"b=4&a=3"
"a=4&a=3"
I'd like to work out the frequency of each value for a certain parameter (a).
value | freq
------|------
3 | 3
2 | 2
4 | 1
Anyway to do this in a single SQL statement?
Something like this:
with all_values as (
select string_to_array(split_part(parameter, '=', 2), ',') as query_params
from the_table d,
unnest(string_to_array(d.querystring, '&')) as x(parameter)
where x.parameter like 'a%'
)
select t.value, count(*)
from all_values av, unnest(av.query_params) as t(value)
group by t.value
order by t.value;
Online example: http://rextester.com/OXM67442
try something like this :
select data_value,count(*) from (
select data_name,unnest(string_to_array(data_values,',')) data_value from (
select split_part(data_array,'=',1) data_name ,split_part(data_array,'=',2) data_values from (
select unnest(string_to_array(mydata,'&')) data_array from mytable
) a
) b
) c where data_name='a' group by 1 order by 1
Assuming tha table that keeps the counts is called paramcount:
WITH vals(v) AS
(SELECT regexp_replace(p, '^.*=', '')
FROM regexp_split_to_table(
'b=4&a=3,2',
'&|,'
) p(p)
)
INSERT INTO paramcount (value, freq)
SELECT v, 1 FROM vals
ON CONFLICT (value)
DO UPDATE SET freq = paramcount.freq + 1
WHERE paramcount.value = EXCLUDED.value;
get csv integer after 'a='
split that to numbers
stat values
select v, count(*) from (
SELECT c,unnest(string_to_array(unnest(regexp_matches(c,'a=([0-9,]+)','g')),',')) as v FROM qrs
) x group by v;
Parametrize:
WITH argname(aname) as (values ('a'::TEXT))
select v, count(*) from (SELECT c,unnest(string_to_array(unnest(regexp_matches(c,aname||'=([0-9,]+)','g')),',')) as v FROM qrs,argname) x group by v;