Check if value exists exactly like that with SQL query (regexp)? - sql

Example json in the socialMedia database column
[{"id":"1463dae5-1168-432e-8e55-c61820d69c49","value":"person2"},
{"id":"c61820d69c49-8e55-432e-8e55-8e55","value":"person1"}]
I want to run a query to check if "value":"person1" or "value:"person2" or something else like that exists in the json field. Is that possible to do with regexp or something?

Using JSON_SEARCH
App\Models\User::whereRaw('JSON_SEARCH(users.name, "all", "%person%")')->get();
Or using JSON_EXTRACT
App\Models\User::where(DB::raw('JSON_EXTRACT(`name`, "$.*")'), 'LIKE', '%person%')->get();

Related

BigQuery IF condition then append value into Array - Standard SQL

In BQ (Standard SQL) I would like to Append a value into an existing Array IF a condition is satisfied
example
IF (REGEXP_CONTAINS(prodTitle, r'(?i)ecksofa'),ARRAY_CONCAT(prodcategory, ("1102")))
is this correct and efficient?
can I use multiple IFs and ARRAY_CONCAT in the same Query?
example
IF (REGEXP_CONTAINS(prodTitle, r'(?i)ecksofa'),ARRAY_CONCAT(prodcategory, ("1102")))
IF (REGEXP_CONTAINS(prodTitle, r'(?i)blablan'),ARRAY_CONCAT(prodcategory, ("1103")))
Guess your purpose is like below for single IF (corrected your expression a little bit):
IF (REGEXP_CONTAINS(prodTitle, r'(?i)ecksofa'),
ARRAY_CONCAT(prodcategory, ["1102"]),
prodcategory)
In order to chain multiple IF and concat the output array, I would use SQL like below:
ARRAY_CONCAT(prodcategory,
IF (REGEXP_CONTAINS(prodTitle, r'(?i)ecksofa'), ["1102"], []),
IF (REGEXP_CONTAINS(prodTitle, r'(?i)blablan'), ["1103"], []),
...
)
To be more efficient, it is better to replace
REGEXP_CONTAINS(prodTitle, r'(?i)ecksofa')
=>
STRPOS(LOWER(prodTitle), 'ecksofa') != 0

Problem with filter in django orm by json field

Could someone help me with django orm filter
I am trying to filter data by some key in json filed (Postgres, jsonb field)
Field in postgres table contains something like
{ "pet": "dog", "name": "my_lovely_dog" }
I build filter like:
cond = {"field_name__pet": some_variable}
qs = qs.filter(**cond)
But when I watch result sql query I see something like:
Select * from "table_name" where ("table"."my_field" -> pet) = '"dog"'
How I can do it correctly? Why django use "" inside ''? And why django not put key from json in ""?
Thank you
The way to resolve this issue is:
I use field__contains = {"dog":"dogs_name"} and it work
#Jim
Thank you

Codeigniter database queries with multiple LIKE parameters

How can I perform a query with multiple LIKE parameters?
For example, I have this string to search through:
"I like searching very much"
This is the code I currently use:
$searTerm = "like"
$this->db->or_like('list.description', $SearchTerm,'both');
But i want to search with 2 or 3 parameters. like this:
$searTerm = "like"
$searTerm1 = "much"
How can i perform this to get the same result?
You can simply repeat the like parameters on the active record. In your example you would do something like this:
$this->db->or_like('list.description', $searchTerm1);
$this->db->or_like('list.description', $searchTerm2);
$this->db->or_like('list.description', $searchTerm3);
...
This will just join each or_like with an AND in the WHERE clause.
Firstly, you need to define the array with like variables then, its very important to put the or_like statement above the where clause in order to make multiple 'OR' statements for like 'AND' the where clause.
Here is example:
$this->db->or_like(array('column_name1' => $k, 'column_name2' => $k))
$this->db->where($whereColumn, $whereValue)
You can use like group
$this->db->group_start()->like('column_name1', $value)
->or_group_start()
->like('column_name2', $value)
->group_end()
->group_end();

Django select only rows with duplicate field values

suppose we have a model in django defined as follows:
class Literal:
name = models.CharField(...)
...
Name field is not unique, and thus can have duplicate values. I need to accomplish the following task:
Select all rows from the model that have at least one duplicate value of the name field.
I know how to do it using plain SQL (may be not the best solution):
select * from literal where name IN (
select name from literal group by name having count((name)) > 1
);
So, is it possible to select this using django ORM? Or better SQL solution?
Try:
from django.db.models import Count
Literal.objects.values('name')
.annotate(Count('id'))
.order_by()
.filter(id__count__gt=1)
This is as close as you can get with Django. The problem is that this will return a ValuesQuerySet with only name and count. However, you can then use this to construct a regular QuerySet by feeding it back into another query:
dupes = Literal.objects.values('name')
.annotate(Count('id'))
.order_by()
.filter(id__count__gt=1)
Literal.objects.filter(name__in=[item['name'] for item in dupes])
This was rejected as an edit. So here it is as a better answer
dups = (
Literal.objects.values('name')
.annotate(count=Count('id'))
.values('name')
.order_by()
.filter(count__gt=1)
)
This will return a ValuesQuerySet with all of the duplicate names. However, you can then use this to construct a regular QuerySet by feeding it back into another query. The django ORM is smart enough to combine these into a single query:
Literal.objects.filter(name__in=dups)
The extra call to .values('name') after the annotate call looks a little strange. Without this, the subquery fails. The extra values tricks the ORM into only selecting the name column for the subquery.
try using aggregation
Literal.objects.values('name').annotate(name_count=Count('name')).exclude(name_count=1)
In case you use PostgreSQL, you can do something like this:
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import Func, Value
duplicate_ids = (Literal.objects.values('name')
.annotate(ids=ArrayAgg('id'))
.annotate(c=Func('ids', Value(1), function='array_length'))
.filter(c__gt=1)
.annotate(ids=Func('ids', function='unnest'))
.values_list('ids', flat=True))
It results in this rather simple SQL query:
SELECT unnest(ARRAY_AGG("app_literal"."id")) AS "ids"
FROM "app_literal"
GROUP BY "app_literal"."name"
HAVING array_length(ARRAY_AGG("app_literal"."id"), 1) > 1
Ok, so for some reason none of the above worked for, it always returned <MultilingualQuerySet []>. I use the following, much easier to understand but not so elegant solution:
dupes = []
uniques = []
dupes_query = MyModel.objects.values_list('field', flat=True)
for dupe in set(dupes_query):
if not dupe in uniques:
uniques.append(dupe)
else:
dupes.append(dupe)
print(set(dupes))
If you want to result only names list but not objects, you can use the following query
repeated_names = Literal.objects.values('name').annotate(Count('id')).order_by().filter(id__count__gt=1).values_list('name', flat='true')

Activerecord Where with a hash value

I have a City model with a cached_info field which is a serialized hash.
{:population=>20000, :more_stuff =>....}
If I make the following query in Activerecord.
City.where('cached_info[:population] > 300').count
I get back...
ActiveRecord::StatementInvalid: Mysql2::Error:
You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near '[:population] > 300)' at line 1: SELECT COUNT(*) FROM `places` WHERE `places`.`type` = 'City' AND (cached_info[:population] > 3)
Anybody have a workaround for this?
There's no easy way to query within a serialised Hash via ActiveRecord and SQL, unless you use a LIKE in your query (but this can't do comparisons like > and <).
Based on your use case you should really rethink your data model and normalise these fields into proper models/columns.
As Jits said, LIKE/ILIKE would work, e.g.:
City.where('cached_info LIKE ?', '%name: Louisiana%')
If you're using PostgreSQL with JSONB fields to store your hashes, you can drop down to SQL in the where and use something like this:
City.where("cast(cached_info ->> 'population' as int) > ?", 300)
The ->> is a Postgres JSONB access operator -- check out this article.