REGEXP_LIKE in SQLAlchemy - sql

Any one knows how could I use the equivalent of REGEXP_LIKE in SQLAlchemy? For example I'd like to be able to do something like:
sa.Session.query(sa.Table).filter(sa.Table.field.like(regex-to match))
Thanks for your help!

It should (I have no access to Oracle) work like this:
sa.Session.query(sa.Table) \
.filter(sa.func.REGEXP_LIKE(sa.Table.c.column, '[[:digit:]]'))

In cases when you need to do database specific function which is not supported by SQLAlchemy you can use literal filter. So you can still use SQLAlchemy to build query for you - i.e. take care about joins etc.
Here is example how to put together literal filter with PostgreSQL Regex Matching operator ~
session.query(sa.Table).filter("%s ~':regex_pattern'" % sa.Table.c.column.name).params(regex_pattern='stack')
or you can manually specify table and column as a part of literal string to avoid ambigious column names case
session.query(sa.Table).filter("table.column ~':regex_pattern'" ).params(regex_pattern='[123]')

This is not fully portable, but here is a Postgres solution, which uses a ~ operator. We can use arbitrary operators thus:
sa.Session.query(sa.Table).filter(sa.Table.field.op('~', is_comparison=True)(regex-to match))
Or, assuming a default precedence of 0,
sa.Session.query(sa.Table).filter(sa.Table.field.op('~', 0, True)(regex-to match))
This also works with ORM constructs:
sa.Session.query(SomeClass).filter(SomeClass.field.op('~', 0, True)(regex-to match))

Related

Looking for information on specific operators in Bigquery, if they exist, and if not, what other operators perform similar functions

I am looking to understand whether or not the below functions are supported in bigquery. I have tried to use them and they are not recognized. If they are not supported, could you recommend what could be used to replace them?
ILIKE operator - case insensitive version of LIKE operator
IGNORE CASE - way to get around not having ILIKE, bigquery does not seem to support
CONTAINS operator - way to get around using wildcard operators with LIKE
Is the only way to do this with the LOWER() operator?
Thanks for the help!
BigQuery is already case sensitive so ILIKE should work with just LIKE.
For IGNORE, since BigQuery is case sensitive you have to use UPPER or LOWER in combination with LIKE. So, UPPER(column) LIKE '%BLAH%'.
For CONTAINS there is REGEXP_CONTAINS, and there is more info here: https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#regexp_contains

String matching in PostgreSQL

I need to implement a regular expression (as I understand) matching in PostgreSQL 8.4. It seems regular expression matching are only available in 9.0+.
My need is:
When I give an input 14.1 I need to get these results:
14.1.1
14.1.2
14.1.Z
...
But exclude:
14.1.1.1
14.1.1.K
14.1.Z.3.A
...
The pattern is not limited to a single character. There is always a possibility that a pattern like this will be presented: 14.1.1.2K, 14.1.Z.13.A2 etc., because the pattern is provided the user. The application has no control over the pattern (it's not a version number).
Any idea how to implement this in Postgres 8.4?
After one more question my issue was solved:
Escaping a LIKE pattern or regexp string in Postgres 8.4 inside a stored procedure
Regular expression matching has been in Postgres practically for ever, at least since version 7.1. Use the these operators:
~ !~ ~* !~*
For an overview, see:
Pattern matching with LIKE, SIMILAR TO or regular expressions in PostgreSQL
The point in your case seems to be to disallow more dots:
SELECT *
FROM tbl
WHERE version LIKE '14.1.%' -- for performance
AND version ~ '^14\.1\.[^.]+$'; -- for correct result
db<>fiddle here
Old sqlfiddle
The LIKE expression is redundant, but it is going to improve performance dramatically, even without index. You should have an index, of course.
The LIKE expression can use a basic text_pattern_ops index, while the regular expression cannot, at least in Postgres 8.4.
Or with COLLATE "C" since Postgres 9.1. See:
Is there a difference between text_pattern_ops and COLLATE "C"?
PostgreSQL LIKE query performance variations
[^.] in the regex pattern is a character class that excludes the dot (.). So more characters are allowed, just no more dots.
Performance
To squeeze out top performance for this particular query you could add a specialized index:
CREATE INDEX tbl_special_idx ON tbl
((length(version) - length(replace(version, '.', ''))), version text_pattern_ops);
And use a matching query, the same as above, just replace the last line with:
AND length(version) - length(replace(version, '.', '')) = 2
db<>fiddle here
Old sqlfiddle
You can't do regex matching, but I believe you can do like operators so:
SELECT * FROM table WHERE version LIKE '14.1._';
Will match any row with a version of '14.1.' followed by a single character. This should match your examples. Note that this will not match just '14.1', if you needed this as well. You could do this with an OR.
SELECT * FROM table WHERE version LIKE '14.1._' OR version = '14.1';
Regex matching should be possible with Postgresql-8.4 like this:
SELECT * FROM table WHERE version ~ '^14\.1\..$';

How to cast a MongoDB query and use Index

I have a sql query that I want to convert to MongoDB and still use the index. Here is the sql query
SELECT * FROM "Data1" WHERE age > Cast('12' as int)
According to this SO answer the above query can be converted to:
db.test.find("this.age > 12")
However, using this syntax will not use any indexes. I wanted to know has this issue has been fixed for MonoDB.
You need to use the $gt operator, to make use of indexes.
db.test.find({age:{$gt:12}})
The field age should be indexed.
I wanted to know has this issue has been fixed for MongoDB.
It still can't be achieved.
The doc says, If you need to use java script for evaluation and select documents, you need to use the $where operator. But it would not use the index.
db.test.find( { $where: "this.age>12" } );
From the docs,
$where evaluates JavaScript and cannot take advantage of indexes;
Hence whenever query criteria is evaluated as Java script , it can never make use of indexes.

String matching in Peewee (SQL)

I am trying to query in Peewee with results that should have a specific substring in them.
For instance, if I want only activities with "Physics" in the name:
schedule = Session.select().join(Activity).where(Activity.name % "%Physics%").join(Course).join(StuCouRel).join(Student).where(Student.id == current_user.id)
The above example doesn't give any errors, but doesn't work correctly.
In python, I would just do if "Physics" in Activity.name, so I'm looking for an equivalent which I can use in a query.
You could also use these query methods: .contains(substring), .startswith(prefix), .endswith(suffix).
For example, your where clause could be:
.where(Activity.name.contains("Physics"))
I believe this is case-insensitive and behaves the same as LIKE '%Physics%'.
Quick answer:
just use Activity.name.contains('Physics')
Depending on the database backend you're using you'll want to pick the right "wildcard". Postgresql and MySQL use "%", but for Sqlite if you're performing a LIKE query you will actually want to use "*" (although for ILIKE it is "%", confusing).
I'm going to guess you're using SQLite since the above query is failing, so to recap, with SQLite if you want case-sensitive partial-string matching: Activity.name % "*Physics*", and for case-insensitive: Activity.name ** "%Physics%".
http://www.sqlite.org/lang_expr.html#like

How to implement "like" in BigQuery?

I am trying to run a simple query making a restriction of like % in BigQuery, but LIKE is not in their syntax, so how can it be implemented?
You can use the REGEXP_MATCH function (see the query reference page):
REGEXP_MATCH('str', 'reg_exp')
Instead of using the % syntax used by LIKE, you should use regular expressions (detailed syntax definition here)
LIKE is officially supported in BigQuery Standard SQL -
https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#comparison_operators
And I think it also works in Legacy SQL!
REGEXP_MATCH returns true if str matches the regular expression. For string matching without regular expressions, use CONTAINS instead of REGEXP_MATCH.
https://developers.google.com/bigquery/docs/query-reference#stringfunctions
REGEXP_MATCH is great if you know how to use it, but for those who aren't sure there won't be any commonly used special characters such as '.','$' or '?' in the lookup string, you can use LEFT('str', numeric_expr) or RIGHT('str', numeric_expr).
ie if you had a list of names and wanted to return all those that are LIKE 'sa%'
you'd use:
select name from list where LEFT(name,2)='sa'; (with 2 being the length of 'sa')
Additionally, if you wanted to say where one column's values are LIKE another's, you could swap out the 2 for LENGTH(column_with_lookup_strings) and ='sa' for =column_with_lookup_strings, leaving it looking something like this:
select name from list where LEFT(name,LENGTH(column_with_lookup_strings))= column_with_lookup_strings;
https://cloud.google.com/bigquery/query-reference