patternsqlMinor
Postgresql: Pattern match against array elements?
Viewed 0 times
postgresqlelementsarraymatchagainstpattern
Problem
Is there any way to do a pattern match against the elements of an array in postgresql (9.4 if the version makes a difference)? I have an aggregate function that, among other things, returns an array of elements, like:
Where the
But while this doesn't give an error, it also doesn't return any results. I'm guessing that this is because the wild card is on the left of the operator. Of course, turning it around to be:
gives me a syntax error. So is there any way I can run this query such that I get any rows containing a flight number that starts with an 8 (or whatever)?
Please note that this is a simplified example demonstrating just the section I am having difficulty with.
SELECT
lognum
,array_agg(flightnum) as flightnums
FROM logs
GROUP BY lognum;Where the
flightnum field is a varchar containing either a text string or a three-or-four digit number. Now say I want to select all logs that have a flight number starting with an '8' (so '800' or '8000' series flights). My first thought was to do something like this:SELECT
*
FROM (
SELECT
lognum
,array_agg(flightnum) as flightnums
FROM logs
GROUP BY
lognum
) s1
WHERE
'8%' like ANY(flightnums);But while this doesn't give an error, it also doesn't return any results. I'm guessing that this is because the wild card is on the left of the operator. Of course, turning it around to be:
WHERE ANY(flightnum) like '8%'gives me a syntax error. So is there any way I can run this query such that I get any rows containing a flight number that starts with an 8 (or whatever)?
Please note that this is a simplified example demonstrating just the section I am having difficulty with.
Solution
What I ended up doing was writing a "commutator" operator. In postgres I created a new function and operator using the following two commands:
Which is effectively identical to a
Note that this may not be the most performant solution - it's quite possible that the answer from Cassandra would be better if you require maximum performance. However, this works well for me, as it doesn't require any changes to the structure of the query.
create function like_rev (text, text) returns boolean as $ select $2 like $1 $ language SQL;
create operator ~~~~ (procedure = like_rev, leftarg=text, rightarg=text);Which is effectively identical to a
like, but reverses the argument order when comparing. So now I can accomplish my goal of doing a wildcard match against an array by simply replacing like with ~~~~, like so:SELECT
*
FROM (
SELECT
lognum,
array_agg(flightnum) as flightnums
FROM logs
GROUP BY
lognum
) s1
WHERE
'8%' ~~~~ ANY(flightnums);Note that this may not be the most performant solution - it's quite possible that the answer from Cassandra would be better if you require maximum performance. However, this works well for me, as it doesn't require any changes to the structure of the query.
Code Snippets
create function like_rev (text, text) returns boolean as $$ select $2 like $1 $$ language SQL;
create operator ~~~~ (procedure = like_rev, leftarg=text, rightarg=text);SELECT
*
FROM (
SELECT
lognum,
array_agg(flightnum) as flightnums
FROM logs
GROUP BY
lognum
) s1
WHERE
'8%' ~~~~ ANY(flightnums);Context
StackExchange Database Administrators Q#117767, answer score: 5
Revisions (0)
No revisions yet.