Mysql search in concatinated string - mysql

There is a table:
CREATE TABLE n_dummy (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
`values` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
INSERT INTO `n_dummy` (id, `values`) VALUES
(2, '2,10'),
(10, '2,10')
(3, '7,3');
Look like this:
id | values
-----------
2 | 2,10
10 | 2,10
3 | 7,3
Fiddle included.
The first column is the integer to be searched in string from values column.
Note: Example is too simplified and looks stupid. Refactoring table structure is not the way. Only sql query with standard functions and procedures.
I want to search integer value in string, concatenated from integers with , separator.
I expects MySQL to do this with IN operator:
SELECT id
FROM n_dummy
WHERE id IN(values);
And result would be 2, 10 and 3. But MySQL returns only 2, the second and other values is not searchable with IN operator with string.
How to search integer in concatenated string using sql-query and prebuild routines?

try this brother
SELECT * FROM `n_dummy` WHERE concat(',',`values`,',') LIKE concat('%',',',`id`,',','%')

Related

How to find specific value from MySQL json(or text) column?

How to find specific value from MySQL json(or text) column? Row example:
'profile': [{'name':['John', 'Smith'], 'interest':['Sports', 'Games']}]
in above example, I want to search 'John' or 'Sports' without specifying key('name' or interests). MySQL official guide says you have to specify column name, but in my case it's preferred not to choose column name.
Another question is search performance if there are hundreds of thousands of rows in the table.
Use the JSON_SEARCH() function in MySQL 5.7 and later. It returns the path within the JSON document to the value you're searching for:
mysql> set #j = '{"profile": [{"name":["John", "Smith"], "interest":["Sports", "Games"]}]';
mysql> select json_search(#j, 'one', 'John') as path;
+------------------------+
| path |
+------------------------+
| "$.profile[0].name[0]" |
+------------------------+
But I recommend using normal columns instead of JSON if you need to search for values. In other words, you shouldn't ever reference a JSON column in the WHERE clause of a query.
In this case, you should have tables like this:
CREATE TABLE profile (
id SERIAL PRIMARY KEY,
first_name VARCHAR(24) NOT NULL,
last_name VARCHAR(24) NOT NULL
);
CREATE TABLE profile_interests (
id SERIAL PRIMARY KEY,
profile_id BIGINT UNSIGNED NOT NULL,
interest VARCHAR(24) NOT NULL,
FOREIGN KEY (profile_id) REFERENCES profile(id)
);
Then search using queries for the column you want.
P.S.: I fixed the quotes in your JSON document. You used single quotes like ' but you must use double quotes like " for it to be valid JSON format.
I found one solution - use fulltext search in MySQL that json string can be searched with keywords.

how to store a 10 digit number into sql bigint datatype?

When I try to enter value through PHP, 2147483647 is getting stored.
NOTE: 2147483647 is the max size for int datatype not bigint in mysql.
Maximum value that can be stored in MySQL INT datatype is 2147483647.
MySQL will silently truncate larger values down to the maximum supported value.
This is expected (i.e. documented) behavior.
Reference: https://dev.mysql.com/doc/refman/5.7/en/integer-types.html
datataype maximum signed value
--------- --------------------
TINYINT 127
SMALLINT 32767
MEDIUMINT 388607
INT 2147483647
BIGINT 2^63-1
If we are seeing this behavior storing to a BIGINT column, then somewhere in the code path, the value got converted to INT datatype, which truncated the value, before the value was assigned to the BIGINT column. This could occur as the return from a function call, or in an assignment of the value in a TRIGGER, et al.
It's not possible to more precisely diagnose the issue with the information provided.
How to store a value to a BIGINT column?
We can send a string literal in a SQL statement. As a demonstration, twelve decimal digits
CREATE TABLE foo (mycol BIGINT);
INSERT INTO foo (mycol) VALUES ('987645312745');
SELECT mycol FROM foo;
mycol
-------------
987645312745
I see no issue:
create table my_number (
val bigint
);
insert into my_number (val) values (1234567890);
insert into my_number (val) values (123456789012345678);
select * from my_number;
Result:
val
----------------------
1234567890
123456789012345678
Edit: Adding new example posted as comment:
CREATE TABLE contacts_db (
Fname varchar(15) NOT NULL,
Lname varchar(15) NOT NULL,
Email varchar(35) NOT NULL,
Phone bigint(10) UNSIGNED NOT NULL
);
insert into contacts_db (Fname, Lname, Email, Phone)
values ('a', 'b', 'c', 1234567890);
insert into contacts_db (Fname, Lname, Email, Phone)
values ('d', 'e', 'f', 123456789012345678);
select * from contacts_db;
Result:
Fname Lname Email Phone
----- ----- ----- ------------------
a b c 1234567890
d e f 123456789012345678
Still works well.
Thanks guys for answering the question. The problem was due to a typecasting done on the PHP side, by mistake I typecasted the value to (int) while retrieving the input from HTML page.

how to perform a SELECT on a JSON column in mysql/mariaDB

how to apply WHERE clause on JSON column to perform a SELECT query on a table which is having two columns (id Integer, attr JSON). The JSON is nested and in the filter condition there is only one key value pair of json is allowed. This key value pair can be anywhere in the Josn.
+----+-----------------------------------------------------------------
| id | attr
|
+----+-----------------------------------------------------------------
| 1 | {"id":"0001","type":"donut","name":"Cake","ppu":0.55}
|
| 2 | {"id":"0002","type":"donut","name":"Cake","ppu":0.55,"batters":
{"batter1":100,"batter2":200}}
+----+-----------------------------------------------------------------
In MariaDB 10.2, you can use the JSON functions.
For example, if you want to SELECT all donuts from your database, you do:
SELECT * FROM t WHERE JSON_CONTAINS(attr, '"donut"', '$.type');
Note: In MariaDB, JSON functions work with all text data types (VARCHAR, TEXT etc.). The JSON type is simply an alias for LONGTEXT.
Similarly to markusjm's answer, you can select directly from the json by field like:
SELECT json_extract(attr, '$.type') FROM t;
If you are still using MySQL 5.6 (has no JSON parsing support) we can use the substring_index functions to parse json data.
Here is a working example:
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`attr` longtext COLLATE utf8_unicode_ci NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO products (attr, created_at)
VALUES
('{"id":"0001","type":"donut","name":"Cake","ppu":0.55}', now()),
('{"id":"0002","type":"donut","name":"Cake","ppu":0.55,"batters":{"batter1":100,"batter2":200}}', now()),
('{"id":"0003","type":"apple","name":"Apple","ppu":0.60}', now()),
('{"id":"0003","type":"orange","name":"Orange","ppu":0.65}', now());
select
substring_index(substring_index(attr, '"type":"', -1), '",', 1) AS product_type
from products
having product_type = 'donut';

Mysql ignore contition 'where' on varchar primary key

I have table
DROP TABLE IF EXISTS `slug`;
CREATE TABLE `slug` (
`slug` varchar(255) NOT NULL,
`id` int(10) unsigned NOT NULL,
`table` varchar(64) NOT NULL,
PRIMARY KEY (`slug`),
UNIQUE KEY `id_table` (`id`,`table`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `slug` (`slug`, `id`, `table`) VALUES
('aaa', 3, 'team');
I have select
SELECT `slug`, `id`, `table`
FROM `slug`
WHERE (`slug` = 0)
and result is
+------+----+-------+
| slug | id | table |
+------+----+-------+
| aaa | 3 | team |
+------+----+-------+
Condition is slug = 0, but I get row where slug is 'aaa'.
Any idea?
Mysql version 5.5.38-0ubuntu0.12.04.1
As a note, it is a bad idea to use reserved words, such as table as column names. This however is irrelevant to your question.
The important part of the query is:
WHERE slug = 0
How does MySQL handle this? What can it do? After all, you've declared slug to be a varchar() but it is being compared to an integer. Well, what MySQL does is silent conversion to the numeric type. So, it converts the value in slug to an integer.
Which integer? If slug were '123', then it would be easy. The value would be 123. Instead, the value is aaa. MySQL's conversion rules are to convert the leading "digits" of the string to a number, until are no more "digits". When there are no digits at all, the value is 0. I've put digits in quotes because it includes '-', '.', and 'e' (for exponential notation).
So, your where clause is comparing any string that doesn't start with a numeric 0 to 0. The following values should all pass: 'aaa', 'zzz', '0abc', and so on.
This is expected behavior.
In MySQL, a zero number can be equal to any string.
So when you want to compare a string with a value of an integer column, you have to cast your integer value into a string.

Problem with an querying an array. (MySQL/PHP)

I have an array of strings inputted by the user from an dynamic form. I want to store each value of the array into a table along with an itemid (which is the same for all)
My query is currently inserting the whole array into one row's text_value with implode.
Is there a way instead of looping through the array and running a query for each value in the array, for me to query each array value with the itemId.
I was thinking perhaps adding another dimension to the array with the itemId? is this possible?
current query:
$query = "INSERT INTO answers_tb (item_id, text_value)VALUES('$itemid','".implode(',', $answers) . "')";
here is print_r of array:
Array ( [0] => option 1 [1] => option 2 [2] => option 3 [3] => option 4 )
here is the table structure I am inserting to (item_id is a foreign key):
**Field** | **Type** **Attributes**
answer_id | int(11) PRIMARY KEY
item_id | int(11) FOREIGN KEY
text_value | varchar(50)
the referenced table:
**Field** | **Type** | **Attributes**
item_id | int(11) | PRIMARY KEY
item_type | tinyint(1) |
user_id | int(11) |
unit_id | int(11) |
question_text | varchar(100)
question_text_2 | varchar(100)
item_desc | varchar(25)
item_name | varchar(25)
thanks
If you structure your table as item_id, astring rather than item_id, alongconcatenatedstring, you could do the insert like this:
$id=2;
$valueclause=function($string) use ($id) { return "('$id','$string')";};
array_walk($valueclause, $arr);
$values=implode(',',$arr);
$query= "INSERT INTO answers_tb (item_id, text_value) VALUES $values";
ETA: It appears that it might be useful to have a primary key that combines an auto_increment and another column. So given your table struture of:
**Field** | **Type**
answer_id | int(11)
item_id | int(11)
text_value | varchar(50)
you might consider indexing like this:
CREATE TABLE answers_tb(
item_id INT NOT NULL,
answer_id INT NOT NULL AUTO_INCREMENT,
text_value CHAR(50) NOT NULL,
PRIMARY KEY (item_id, answer_id)//note the 2 columns in the key
);
Then when you insert like this:
INSERT INTO answers_tb (item_id, text_value)
VALUES (1,'thing'), (1,'foo'),
(17,'blah'),
(6,'beebel'), (6,'bar');
your resulting data will look like this:
item_id, answer_id, textvalue
1, 1, thing
1, 2, foo
17, 1, blah
6, 1, beebel
6, 2, bar
It sounds like you would be better served with a different table design.
Instead of answers_tb (item_id, text_value), use answers_tb (item_id, offset, value).
(The primary key would be (item_id, offset).)
Then you would find it much easier to query the table.
EDIT: You posted the following table structure:
**Field** | **Type** **Attributes**
answer_id | int(11) PRIMARY KEY
item_id | int(11) FOREIGN KEY
text_value | varchar(50)
If I understand the table design right, your design works like this:
Each row of the referenced table (let's call it questions) represents a single question asked by a user of your application. It has a question ID, and the ID of the user who posted it.
Each row of the table answers_tb represents the set of all answers to the question in the row of table questions referenced by item_id. Answers are distinguished by the order in which they appear in the column entry.
What I'm saying is that this design for answers_tb doesn't work very well, for the reason you've identified: it's difficult to query against the answers stored in the "array" column. That is why this design is problematic. A better design would be as follows:
**Field** | **Type**
item_id | int(11)
answer_number | int
text_value | varchar(50)
wherein item_id is still a foreign key, but the primary key is (item_id, answer_number). In this design, each row of the table, rather than containing the set of all answers to the corresponding question, would contain just one answer to that question. The rows are distinguished from one another by the different values in answer_number, but you know which question each row corresponds to by the value in item_id. This design is much easier to query against.
It is a general rule that you ought not to try to store an array of data in a column, because it makes it problematic to search against. In some cases it makes sense to break that rule, but you have to be able to recognise when you are in such a case. In this case, you want to search by the stored values, so you should not do it.