MYSQL match csv keywords column [duplicate] - mysql

This question already has answers here:
MySQL query finding values in a comma separated string
(11 answers)
Closed 7 years ago.
I have records in user table in following manner
id name address keywords
1 thompsan paris 10,20,30
2 samson paris 10,20,30
3 Nilawa paris 10,20,30
4 Nalama paris 100,30,50
5 Nalama paris 100,300,20
I need to get the users who have the keywords of 10 or 20. I have written this query:
SELECT * from User where keywords REGEXP '[[:<:]]10|20[[:>:]]'
It does not give me the expected output. It should filter for id 10 or 20 and give me the output of record 1,2,3,5. record 4 is not matching here.
Why is it not working? Is there a better way to do this?

Try this,
SELECT *
FROM user
WHERE FIND_IN_SET('10', keywords) > 0 OR
FIND_IN_SET('20', keywords) > 0
FIND_IN_SET is a builtin function with MySQL

Redesign your database so that it's actually in 1NF and you won't have to deal with these headaches not to mention the horrible performance and bugs that it's bound to bring you down the line.
Since I know that you won't do that though, there's no need to use REGEXP at all, assuming that your string in keywords is actually consistent (and if it's not then you're screwed anyway). Just use LIKE:
SELECT -- We'll list out the columns, since we NEVER use SELECT *
id,
name,
address,
keywords
FROM
User
WHERE
',' + keywords + ',' LIKE '%,10,%' OR
',' + keywords + ',' LIKE '%,20,%'

Related

Search For The Comma Separated Values In MYSQL Column [duplicate]

This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 2 years ago.
genreTable:
id
genre
1
Pop
2
Rock
3
Electro
songTable:
id
name
genre
1
Song1
1
2
Song2
1,2
3
Song3
2,3
Problem: Lets say I want to build query like:
SELECT * FROM songTable WHERE genre = '1'
It'll only return Song1
But how Do I make sure it also returns Song1, Song2
Any other suggestions regarding re-structuring the table is also accepted...
You should fix your data model! There are many reasons why your data model is broken:
Columns should only contain one value.
Numbers should be stored as numbers, not strings.
Foreign key relationships should be properly declared.
SQL has pretty bad string processing capabilities.
Sometimes, you are stuck with other people's really, really, really bad design decisions. In that case, you can use find_in_set():
select s.*
from songTable s
where find_in_set('1', genre) > 0

How to compare comma separated field with column in mysql? [duplicate]

This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 4 years ago.
What I have with me?
A string with comma separated :
$str_states = "1,2";
I have a table with the following:
id event_name states
1 ABC 1,4,5
2 PQR 1,2,3
3 XYZ 3,4,5
What I want:
id event_name states
1 ABC 1
2 PQR 1,2
What I tried with a query:
SELECT id,event_name FROM events_table WHERE
FIND_IN_SET('1,2', states);
SELECT id,event_name FROM events_table WHERE
states IN ('51,58');
You can't really use FIND_IN_SET the way you want here. FIND_IN_SET searches for a single value against a CSV string. So, you would have to use OR here:
SELECT id, event_name
FROM events_table
WHERE FIND_IN_SET('1', inLocationId) > 0 OR FIND_IN_SET('2', inLocationId) > 0;
If your starting point for the input is 1,2, then you will have to tease apart the individual values in your app layer.
By the way, storing CSV unnormalized data in your SQL tables is bad practice. You would be better off to fix your design than to use my answer.
As a bonus, here is a more terse way to write your query using REGEXP:
SELECT id, event_name
FROM events_table
WHERE inLocationid REGEXP '[[:<:]](1|2)[[:>:]]';
But again, please fix your data model.

How to find entries matching a specific string

I have more than 50000 records in my table with two columns (id and basic) looks like this
ID
BASIC
1
XXX111XXX111
2
XXXX22221111
3
111XXXXX2212
4
2X1X212X1X1X
5
X21X12X1X12X
What I need is to display only records that consist of 5 "X" that are not adjacent. for example, from the above records i need to get data like this
ID
BASIC
4
2X1X212X1X1X
5
X21X12X1X12X
What query will suite to retrieve such record from my database.
I interpret this as meaning that you want 5 Xs that are not adjacent. I think this does what you want:
where concat(' ', col, ' ') regexp '([^X]+[X]){5}[^X]'
The concat() just takes care of the situation where the first or last character is an "X".

Is there a possibility to change the order of a string with numeric value

I have some strings in my database. Some of them have numeric values (but in string format of course). I am displaying those values ordered ascending.
So we know, for string values, 10 is greater than 2 for example, which is normal. I am asking if there is any solution to display 10 after 2, without changing the code or the database structure, only the data.
If for example I have to display values from 1 to 10, I will have:
1
10
2
3
4
5
6
7
8
9
What I would like to have is
1
2
3
4
5
6
7
8
9
10
Is there a possibility to ad an "invisible character or string which will be interpreted as greater than 9". If i put a10 instead of 10, the a10 will be at the end but is there any invisible or less visible character for that.
So, I repeat, I am not looking for a programming or database structure solution, but for a simple workaround.
You could try to cast the value as an number to then order by it:
select col
from yourtable
order by cast(col AS UNSIGNED)
See SQL Fiddle with demo
You could try appending the correct number of zeroes to the front of the data:
01
02
03
..
10
11
..
99
Since you have a mixture of numbers and letters in this column - even if not in a single row - what you're really trying to do is a Natural Sort. This is not something MySQL can do natively. There are some work arounds, however. The best I've come across are:
Sort by length then value.
SELECT
mixedColumn
FROM
tableName
ORDER BY
LENGTH(mixedColumn), mixedColumn;
For more examples see: http://www.copterlabs.com/blog/natural-sorting-in-mysql/
Use a secondary column to use as a sort key that would contain some sort of normalized data (i.e. only numbers or only letters).
CREATE TABLE tableName (mixedColumn varchar, sortColumn int);
INSERT INTO tableName VALUES ('1',1), ('2',2), ('10',3),
('a',4),('a1',5),('a2',6),('b1',7);
SELECT
mixedColumn
FROM
tableName
ORDER BY
sortColumn;
This could get difficult to maintain unless you can figure out a good way to handle the ordering.
Of course if you were able to go outside of the database you'd be able to use natural sort functions from various programming languages.

Multiple LIKE in SQL

I wanted to search through multiple rows and obtain the row that contains a particular item.
The table in mySQL is setup so each id has a unique list (comma-delimited) of values per row.
Ex:
id | order
1 | 1,3,8,19,34,2,38
2 | 4,7,2,190,38
Now if I wanted to pull the row that contained just the number 19 how would I go about doing this? The possibilities I could figure in the list with a LIKE condition would be:
19, <-- 19 at the start of the list
,19 <-- 19 at the end of the list
,19, <-- 19 inside the list
I tried the following and I cannot obtain any results, Thank you for your help!
SELECT *
FROM categories
WHERE order LIKE '19,%' OR '%,19%' OR '%,19%'
LIMIT 0 , 30
First of all, you should not store values like this, you should use a child table with one row per item, this would make your current query that much easier to handle, and would allow for indexes to be used as well.
Having said that, what you want is this:
WHERE ',' + order + ',' LIKE '%,19,%'
By adding a comma in front of and after the list of values in the order field, you can query that field for the value you want with a comma on each side, and not have to deal with the special case of the value being the first or last value in the list.
With the query you listed, you could've made it work by realizing that OR doesn't give more arguments to the LIKE clause, it separates entirely different clauses, and thus rewritten the SQL like this:
WHERE order LIKE '19,%' OR order LIKE '%,19,%' OR order LIKE '%,19'
---+------ ^ ----+----- ^
| | | |
+- add this -+---------+ +- removed
percent
Note the missing comma in the second pattern there, which would match strings containing the value 19, and note the removed percentage character in the last ,which would allow it to match lists that ended with 19.
You can use FIND_IN_SET to solve your problem in a simpler way:
SELECT *
FROM categories
WHERE FIND_IN_SET('19', `order`)
LIMIT 0, 30
In general though you should try to design your database so that this type of operation is not necessary.