mysql where type int - mysql

my table 'users' have a following schema
| id | name | class|
| 0 | John | Primary |
| 1 | Mary | Primary |
I tried this query:
select * from users where id = 'a'
The mysql return all rows from table.
How can I solve this problem?

If id is of type Integer, you have to type it without quotation marks. For example:
select * from users where id = 0;
should return:
| 0 | John | Primary
However, the 'a' in your example is not an Integer, so I am not 100 percent sure where this comes from and if I understood you correctly.

Related

How can I insert data to table B with more columns than table A with the same ID (ID matches from both tables)?

So here is my problem, how can i do this :
user with ID = 7 from table A with 3 columns want to insert data to table B with 4 columns but with the same id.
Table A :
| Id | name | password |
| 7 | john | password |
| 9 | mark | password |
| 12 | yuta | password |
Table B :
| Id | user_id | food | drink |
| 1 | 7 | oats | milk |
| 2 | 9 | fish | water |
| 3 | 12 | pear | fanta |
How can i achieve table b in 1 query? both id in both table are primary keys and im using mysql
here's the code i was trying to do :
INSERT INTO table_b SET food = :food, drink = :drink, ( user_id) SELECT a.id FROM table_a u WHERE EXISTS (SELECT * WHERE name = :name AND password = :password)
i know the query is wrong but thats the closest i can do. pls help thank you
You should just use a unique code to link them together.
you can have the code stored in a variable like this
$unique = time().rand(1000, 9999);
//You should have something like this 16659154332358
Create a column that will recieve this value in your database.
Now they have a relationship

How to calculate count of each value in MySQL JSON array?

I have a MySQL table with the following definition:
mysql> desc person;
+--------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | text | YES | | NULL | |
| fruits | json | YES | | NULL | |
+--------+---------+------+-----+---------+-------+
The table has some sample data as follows:
mysql> select * from person;
+----+------+----------------------------------+
| id | name | fruits |
+----+------+----------------------------------+
| 1 | Tom | ["apple", "orange"] |
| 2 | John | ["apple", "mango"] |
| 3 | Tony | ["apple", "mango", "strawberry"] |
+----+------+----------------------------------+
How can I calculate the total number of occurrences for each fruit? For example:
+------------+-------+
| fruit | count |
+------------+-------+
| apple | 3 |
| orange | 1 |
| mango | 2 |
| strawberry | 1 |
+------------+-------+
Some research shows that the JSON_LENGTH function can be used but I cannot find an example similar to my scenario.
You can use JSON_EXTRACT() function to extract each value ("apple", "mango", "strawberry" and "orange") of all three components of the arrays, and then then apply UNION ALL to combine all such queries:
SELECT comp, count(*)
FROM
(
SELECT JSON_EXTRACT(fruit, '$[0]') as comp FROM person UNION ALL
SELECT JSON_EXTRACT(fruit, '$[1]') as comp FROM person UNION ALL
SELECT JSON_EXTRACT(fruit, '$[2]') as comp FROM person
) q
WHERE comp is not null
GROUP BY comp
Indeed If your DB's version is 8, then you can also use JSON_TABLE() function :
SELECT j.fruit, count(*)
FROM person p
JOIN JSON_TABLE(
p.fruits,
'$[*]' columns (fruit varchar(50) path '$')
) j
GROUP BY j.fruit;
Demo
You can't do it without first creating a table with one row per fruit.
CREATE TABLE allfruits (fruit VARCHAR(10) PRIMARY KEY);
INSERT INTO allfruits VALUES ('apple'), ('orange'), ('mango'), ('strawberry');
There is not a good way to generate this from the JSON.
Once you have that table, you can join it to the JSON and then use GROUP BY to count the occurrences.
SELECT fruit, COUNT(*) AS count
FROM allfruits
JOIN person ON JSON_SEARCH(person.fruits, 'one', fruit) IS NOT NULL
GROUP BY fruit;
Output:
+------------+-------+
| fruit | count |
+------------+-------+
| apple | 3 |
| mango | 2 |
| orange | 1 |
| strawberry | 1 |
+------------+-------+
Note that it will do a table-scan on the person table to find each fruit. This is pretty inefficient, and as your person table gets larger, it will become a performance problem.
If you want to optimize for this type of query, then you shouldn't use JSON to store an array of fruits. You should store data in a normalized way, representing the many-to-many relationship between persons and fruits with another table.
This is related to my answer to Is storing a delimited list in a database column really that bad?
I think the simplest solution would be to use JSON_TABLE function.
The query you need is
select ft.fruit, count(ft.fruit) from person,
json_table(
fruits,
'$[*]' columns(
fruit varchar(128) path '$'
)
) as ft
group by ft.fruit
;
You can find working example in this dbfiddle
Fruit demo

Mysql select query using NOT IN / LIKE to retrieve the data

I need to fetch the data in mysql using select query as below
Select tid from abc where abc.parameter not like '%DONE%'
But data return where parameter column have %DONE% VALUE.
Here I am giving sample data for better understanding
tid parameter value
***************************
1 abc 123
1 def 456
1 ghi 789
I need to retrieve tid where def not in .
Schema
create table abc
( id int auto_increment primary key,
tid int not null,
parameter varchar(20) not null,
value int not null
);
insert abc(tid,parameter,value) values (1,'abc',123),(1,'def',456),(1,'ghi',789);
Queries
select id,tid from abc where abc.parameter not like '%DONE%';
+----+-----+
| id | tid |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
+----+-----+
select id,tid from abc where abc.parameter not like '%abc%';
+----+-----+
| id | tid |
+----+-----+
| 2 | 1 |
| 3 | 1 |
+----+-----+
Looks as expected to me.
Note, NOT IN is dangerous in the case of NULLs. One must know there data well, else use NOT EXISTS
Your tid is same, the returned data might be right, but due to ambiguity in your tid you feel that you are getting wrong result.

Select from table A if not exist then table B

I have two tables as bellow,
table A:
+------+----------------+
| TYPE | EMAIL |
+------+----------------+
| 0 | test1#mail.com |
| 1 | test2#mail.com |
| 2 | test3#mail.com |
table B:
+------+----------------+
| ID | EMAIL |
+------+----------------+
| 1 | test1#mail.com |
| 2 | test4#mail.com |
| 3 | test5#mail.com |
I need to check the email address from both table with following criteria,
Check in the table A, IF EXISTS select the TYPE
IF it is not in table A, then check it in table B select the ID
even it is not in table B empty results as normal select query
I can do this with two quires, But my question is whether there is any possibility to do it with one single query ?
Thanks in advance.
This is an alternative: I hope it can be useful anyway.
(SELECT NULL AS ID, EMAIL, TYPE FROM A WHERE EMAIL=<email>)
UNION
(SELECT ID, EMAIL, NULL AS TYPE FROM B WHERE EMAIL=<email>)
In your application you will retrieve from 0 to 2 results. If you got 1 result, use it (note that you will have a NULL value in ID or TYPE). If you got 2 results, use the one where the TYPE is not NULL.
Using your dataset and "test1#mail.com" as the query parameter, this would be the result of the query:
ID EMAIL TYPE
NULL test1#mail.com 0
1 test1#mail.com NULL

Get distinct results from several tables

I need to implement mysql query to calculate space used by user's mailbox.
A message thread may have multiple messages (reply, follow up) by 2 parties
(sender/recipient) and is tagged with one or more tags (Inbox, Sent etc.).
The following conditions have to be met:
a) user is either recipient OR author of the message;
b) message IS TAGGED by any of the tags: 1,2,3,4;
c) distinct records only, ie if the thread, containing messages is tagged with
more than one of the 4 tags (for example 1 and 4: Inbox and Sent) the calculation
is done on one tag only
I have tried the following query but I am not able to get distinct values - the
subject/body values are duplicated:
SELECT SUM(LENGTH(subject)+LENGTH(body)) AS sum
FROM om_msg_message omm
JOIN om_msg_index omi ON omm.mid = omi.mid
JOIN om_msg_tags_index omti ON omi.thread_id = omti.thread_id AND omti.uid = user_id
WHERE (omi.recipient = user_id OR omi.author = user_id) AND omti.tag_id IN (1,2,3,4)
GROUP BY omi.mid;
Structure of the tables:
om_msg_message - fields subject and body are the ones to be calculated
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| mid | int(10) unsigned | NO | PRI | NULL | auto_increment |
| subject | varchar(255) | NO | | NULL | |
| body | longtext | NO | | NULL | |
| timestamp | int(10) unsigned | NO | | NULL | |
| reply_to_mid | int(10) unsigned | NO | | 0 | |
+--------------+------------------+------+-----+---------+----------------+
om_msg_index
+-----+-----------+-----------+--------+--------+---------+
| mid | thread_id | recipient | author | is_new | deleted |
+-----+-----------+-----------+--------+--------+---------+
| 1 | 1 | 1392 | 1211 | 0 | 0 |
| 2 | 1 | 1211 | 1392 | 1 | 0 |
+-----+-----------+-----------+--------+--------+---------+
om_msg_tags_index
+--------+------+-----------+
| tag_id | uid | thread_id |
+--------+------+-----------+
| 1 | 1211 | 1 |
| 4 | 1211 | 1 |
| 1 | 1392 | 1 |
| 4 | 1392 | 1 |
+--------+------+-----------+
Here's another solution:
SELECT SUM(LENGTH(omm.subject) + LENGTH(omm.body)) as totalLength
FROM om_msg_message omm
JOIN om_msg_index omi
ON omi.mid = omm.mid
AND (omi.recipient = user_id OR omi.author = user_id)
JOIN (SELECT DISTINCT thread_id
FROM om_msg_tags_index
WHERE uid = user_id
AND tag_id IN (1, 2, 3, 4)) omti
ON omti.thread_id = omi.thread_id
I'm assuming that:
user_id is a parameter marker/host variable, being queried for an individual user.
You want the total of all messages per user, not the total length of each message (which is what the GROUP BY clause in your version was getting you).
That mid in both om_msg_message and om_msg_index is unique.
So, your problem is the IN clause. I'm not a MYSQL guru, but in T-SQL you could change it to have a where clause on a subquery that contained an EXISTS so your join didn't pop out two rows. You need to compensate for the fact that you have two rows with different tagID's associated with each row of your primary join data.
The way I could do it cross-platform would be with four left-joins that linked tables then demanded a non-null value for 1, 2, 3, or 4. Fairly inefficient; I'm sure there's a better way to do it in MySQL, but now that you know what the problem is you might know a better solution.