MySQL select where JSON field property has value - mysql

How to write a basic MySQL query that has a WHERE on a property within a JSON data-type field? I don't see basic where clause q for json fields on SO.
Something like this, but of course these dont work:
SELECT * from my_table where meta_data->name = 'bob';
SELECT * from my_table where meta_data[name] IS NOT NULL;

Some examples of how to query a json data type field:
SELECT * FROM users WHERE JSON_EXTRACT(meta_data, "$.first_name") = 'bob';
SELECT * FROM users WHERE JSON_EXTRACT(meta_data, "$.age") IS NOT NULL;
SELECT * FROM users WHERE JSON_EXTRACT(meta_data, "$.accepted_policy") = true;
With mysql 5.7.9 +
You can also just do this (shortcut for JSON_EXTRACT):
SELECT * FROM users WHERE meta_data->"$.first_name" = 'bob'
You might notice your json data results are "quoted". You could use JSON_UNQUOTE, or you could use this, which is a shortcut of JSON_EXTRACT & JSON_UNQUOTE:
SELECT meta_data->>"$.first_name" FROM users WHERE meta_data->>"$.first_name" IS NOT NULL
And to select data from within sub objects:
SELECT meta_data->>"$.address.tel" FROM users WHERE meta_data->>"$.address.street" = "123 Main St"
docs: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html

Use Below query for WHERE operation with JSON Datatype Field in mysql
SELECT meta_data->'$.first_name' meta_data FROM users WHERE INSTR(meta_data->'$.first_name','123') > 0

Related

How to access columns of subqueries with jooq?

i am having troubles understanding how to access columns from a subquery (MySQL). Here is my code:
Personne personne = Personne.PERSONNE.as("personne");
Evenement evenement = Evenement.EVENEMENT.as("evenement");
Genealogie genealogie = Genealogie.GENEALOGIE.as("genealogie");
Lieu lieu = Lieu.LIEU.as("lieu");
SelectField<?>[] select = { DSL.countDistinct(personne.ID).as("countRs"), lieu.LIBELLE.as("libelleRs"),
lieu.ID.as("idVille") };
Table<?> fromPersonne = evenement.innerJoin(personne).on(personne.ID.eq(evenement.IDPERS))
.innerJoin(genealogie).on(genealogie.ID.eq(personne.IDGEN)).innerJoin(lieu)
.on(lieu.ID.eq(evenement.IDLIEU));
Table<?> fromFamille = evenement.innerJoin(personne).on(personne.IDFAM.eq(evenement.IDFAM))
.innerJoin(genealogie).on(genealogie.ID.eq(personne.IDGEN)).innerJoin(lieu)
.on(lieu.ID.eq(evenement.IDLIEU));
GroupField[] groupBy = { lieu.ID };
Condition condition = //conditionally build, not relevant i think
result = create.select(DSL.asterisk())
.from(create.select(select).from(fromPersonne).where(condition).groupBy(groupBy)
.union(create.select(select).from(fromFamille).where(condition).groupBy(groupBy)))
// i would like something like this but i don't know how: .groupBy(groupBy).fetch();
Basicly what i have is:
SELECT
*
FROM(
(SELECT
countRs, libelleRs, idVille
FROM
fromPersonne
WHERE
-- conditions
GROUP BY lieu.ID)
UNION
(SELECT
countRs, libelleRs, idVille
FROM
fromFamille
WHERE
-- conditions
GROUP BY lieu.ID)
)GROUP BY lieu.ID -- this is where i need help
In a plain MySQL query i would just give an alias to the union and then make a reference to the column i want to group by using the alias but it seems like it does not work like this with JOOQ.
I just need to group the results of the subqueries together but i don't know how to make a reference to the subqueries columns... I am sure i would have to reference my subqueries in objects outside of that "main select" to be able to access the columns or something along those lines but i am lost in all the object types.
You have to assign your derived table to a local variable and dereference columns from it, e.g.
Table<?> t = table(
select(...).from(...).groupBy(...).unionAll(select(...).from(...).groupBy(...))
).as("t");
Field<Integer> tId = t.field(lieu.ID);

How to SELECT * WHERE JSON keys contain ANY/IN (array of values)

I am dealing with a Symfony "workflow" "Marker" and Postgres. (and Doctrine)
in the db, the column "status" contains JSON data like this
{"needs_address":1,"needs_contacts":1,"needs_education":1,"needs_health_and_social":1,"has_profile_photo":1,"has_letter":1}
I figured out how to query like this
SELECT id, profile_status, beneficiary_code
FROM public.beneficiary_profile
WHERE profile_status->>'needs_address' = '1'
How can I query for a list of status' like
('needs_education','needs_contacts','needs_address')
without writing it all out like
WHERE profile_status->>'needs_address' = '1'
OR profile_status->>'needs_contacts' = '1'
OR profile_status->>'needs_education' = '1'
I figure there must be a way with JSON functions and maybe IN() or ANY()
You will need to unnest the elements in order to be able to use an IN clause, something like:
select *
from public.beneficiary_profile p
where exists (select *
from jsonb_each_text(p.status) as x(ky,val)
where x.ky in ('needs_address', 'needs_contact', 'needs_education')
and x.val = '1');

Compare string to same column in multiple tables mysql

i have a string referring to a jpg file, let's say '34563.jpg'.
Now i want to know if this file is assigned to any record in this 3 tables.
All 3 tables has the same structure
id,name,img
My query just returns true to the first table:
SELECT clients_tbl.img, pets_tbl.img, places_tbl.img
FROM clients_tbl, pets_tbl, places_tbl
WHERE (clients_tbl.img = '34563.jpg')
OR (pets_tbl.img = '34563.jpg')
OR (places_tbl.img = '34563.jpg');
I need a boolean response from this query, it has been found or not.
Thanks
You need UNION:
SELECT COUNT(t.*) when_not_found_0
FROM (
SELECT img
FROM clients_tbl
WHERE clients_tbl.img = '34563.jpg'
UNION
SELECT img
FROM pets_tbl
WHERE pets_tbl.img = '34563.jpg'
UNION
SELECT img
FROM places_tbl
WHERE places_tbl.img = '34563.jpg'
) t
You could set aliases:
SELECT clients_tbl.img as img_clients, pets_tbl.img as img_pets, places_tbl.img as img_places
And later turn the results to booleans.

Need to convert an array to Integer for a MySQL query in a Rails API

I have a piece of code which fetches the list of ids of users I follow.
#followed = current_user.followed_user_ids
It gives me a result like this [11,3,24,42]
I need to add these to NOT IN mysql query.
Currently, I am getting NOT IN ([11,3,24,42]) which is throwing an error. I need NOT IN (11,3,24,42)
This is a part of a find_by_sql statement, so using where.not is not possible for me in this point.
In rails 4:
#followed = current_user.followed_user_ids # #followed = [11,3,24,42]
#not_followed = User.where.not(id: #followed)
This should generate something like select * from users where id not in (11,3,24,42)
As you comment, you are using find_by_slq (and that is available in all rails versions). Then you could use the join method:
query = "select * from users where id not in (#{#followed.join(',')})"
This would raise mysql errors if #followed is blank, the resulting query would be
select * from users where id not in ()
To solve this whiout specifiying aditional if statements to your code, you can use:
query = "select * from users where id not in (0#{#followed.join(',')})"
Your normal queries would be like:
select * from users where id not in (01,2,3,4)
but if the array is blank then would result in
select * from users where id not in (0)
which is a still valid sql statement and is delivering no results (which might be the expected situation in your scenario).
you can do something like:
#followed = [11,3,24,42]
User.where('id not in (?)', #followed)

How to get result with variable in where condition which was set using SET

I have problem in getting the result for below query:
SELECT setting_value FROM system_settings WHERE setting_key='hold_series' INTO #Current;
where 'setting_value' is a text data type and has the value as
50472949,15804527,13613881,13607299,16226328,15774405,14416070.
SELECT * from users where Id in (#Current) [and some left joins];
resulted only one record, I am sure I have all the records in users table.
If I use
SELECT * from users where Id in (50472949,15804527,13613881,13607299,16226328,15774405,14416070)
with left joins , it resulted with all 7 rows. :(
Please let me know what am I doing wrong...
Thanks,
-Jyo
Try to use FIND_IN_SET
SELECT * from users where (FIND_IN_SET(id,#Current)>0)