Order by specific index of comma separated list - mysql

I have data stored in a comma-separated format and I would like to run a query so that the users are ordered by the second value in the column.
So for this sample data:
user | Data
________________________________________
player1 | 45471,2529,32196008193896,99
admin | 1136,2595,17760808279311,95
gamer | 13495,2432,32196008193896,98
________________________________________
The order would be (2595-2529-2432) which is admin => player1 => gamer.

As I mentioned in the comments, you should really try to avoid storing delimited lists like that.
However, you can write a query to parse out the second value by using the SUBSTRING_INDEX() function. This function takes a string, the delimiter character, and an integer whether or not to take from the left/right of the delimiter and for how many. In other words, to get everything left of the second comma, it would look like this:
SELECT SUBSTRING_INDEX(data, ',', 2)
FROM myTable;
Then, from that string, you want everything to the right of the first comma, so you'll have to nest the functions. (Note, this may hurt efficiency, but that's the downfall of delimited lists):
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(data, ',', 2), ',', -1)
FROM myTable;
Then, you can just order by that value:
SELECT *
FROM myTable
ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(data, ',', 2), ',', -1) DESC;
Here is an SQL Fiddle example.

Related

I need to split a mysql field (string) by multiple delimeters into json object

I inherited a mysql database and am trying to migrate it to mongodb. There is a field called details that contains some key value "pairs" I want to split up. There could be a single key/value pair, or multiple pairs split by multiple delimiters. I put pairs in quotes because they are formatted strangely. They are delimited by colon : and key values split by commas ,. For example here is the value of one such field:
Normal Duty,5min:Heavy Duty,10min:Riser,10max:
This is 3 key value pairs, delimited by the colon. I want to get these into a json object if possible, like this:
{
'Normal Duty': '5min',
'Heavy Duty': '10min',
'Riser': '10max'
}
I think I could do it using substring_index if it were only a single key/value pair that had a single delimiter, but I get lost trying to think of a way to extract multiple key/value pairs with multiple delimiters. I'm able to get a count of the number of delimiters, SELECT id, details, LENGTH(details) - LENGTH(REPLACE(details, ':', '')) AS COUNT FROM type but not sure how I could use that number in a loop or something.
SELECT test.id,
JSON_OBJECTAGG(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(test.value, ':', numbers.num), ':', -1), ',', 1),
SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(test.value, ':', numbers.num), ':', -1), ',', -1))
FROM test
CROSS JOIN ( SELECT 1 num UNION SELECT 2 UNION SELECT 3 UNION
SELECT 4 UNION SELECT 5 UNION SELECT 6 ) numbers
WHERE numbers.num <= LENGTH(test.value) - LENGTH(REPLACE(test.value, ':', ''))
GROUP BY test.id
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=d10261e21a0fb1c1060091e8b4e58d80
Adjust numbers subquery if the amount of key-value pairs may be above 6.
PS. To work with JSON I'd strongly recommend to upgrade your server.

MySQL - extract number from data field using SUBSTRING

I'd like to extract the number between NUMBER and ;. So far I can extract the data up to the number, but I don't want anything after the number. e.g.,
SELECT
SUBSTRING(field, LOCATE('NUMBER=', rrule) + 7)
FROM table
Data field:
DATA:PASS=X12;NUMBER=331;FIELD=1
DATA:PASS=X12;NUMBER=2;FOO=BAR;FIELD=1
Desired Output:
331
2
You can use a combination of SUBSTRING_INDEX functions:
SELECT
SUBSTRING_INDEX(
SUBSTRING_INDEX(field, 'NUMBER=', -1),
';',
1)
FROM
tablename
Please see an example fiddle here.
The inner SUBSTRING_INDEX will return everything after the NUMBER= string, while the second will return everything before the ; returned by the inner function.

query to remove all characters after last comma in string

i have a mysql table with this sort of data
TACOMA, Washington, 98477
Now i have thousands of such rows. I want the data to be manipulated in such a manner that it appears like:
TACOMA, Washington
Is it possible though mysql or do i have to manually do it.
You can use :
SELECT SUBSTRING_INDEX('TACOMA, Washington, 98477', ',', 2)
You can read more here.
And the update statement :
UPDATE my_table
SET my_col = SUBSTRING_INDEX(my_col, ',', 2)
Where you need to replace my_table with your table name and my_col with the column you need to be updated.
Possibly this way. Count the number of commas (by checking the length against the length with all the commas removed) and then use SUBSTRING_INDEX to get the string up to the number of commas:-
SELECT SUBSTRING_INDEX(col, ',', LENGTH(col) - LENGTH(REPLACE(col, ',', '')))
FROM SomeTable
substring_index(col, ',',-1)
will give the string from last index of comma to end of string
replace(col,concat(',',substring_index(col, ',',-1)),'')

Is there a FIND_IN_SET by index in MySQL?

I know storing lists as strings is not wise, but I have to deal with that to export some data stored that way. I also know the FIND_IN_SET function, which returns the index of a certain string in a list:
SELECT FIND_IN_SET('bar', 'foo,bar,baz');
-- selects 2
Is there any built-in function (or combination of functions) to get the string in a particular index of the list? I'm looking for something like this:
SELECT IN_SET_AT_INDEX(2, 'foo,bar,baz');
-- selects 'bar'
I'd like to avoid a split-like function that makes the list a separate table, if possible.
SUBSTRING_INDEX() can do this, sort of:
mysql> SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('foo,bar,baz', ',', 2), ',', -1) AS middle_one;
+------------+
| middle_one |
+------------+
| bar |
+------------+
Yes, but it requires just a little trickery. The basis is substring_index(), but that gets everything up to the nth entry. Then I use reverse() twice and another substring_index():
select reverse(substring_index(reverse(substring_index('foo,bar,baz', ',', 2)), ',', 1))
In your case, the transformations are:
original string: 'foo,bar,baz'
after substring_index(..., 2) 'foo,bar'
after inner reverse 'rab,oof'
after substring_index(..., 1) 'rab'
after outer reverse 'bar'

MySQL - Search CSV in CSV Column

I have a table with a column that has CSV.
TableA:
field_id | matches
---------------------
1 1,2,4,6,8,11,14,56
Now I need to get the field_id that matches a user given csv. So for instance, user string is 1,4,11, then it should return some value may be just true.
1.) Find_in_set does not work. Because it takes only one element and searches that in a SET/CSV column.
2.) Cannot use like concat('%,', user_input , ',%'). Because user input may not be in order.
Any other ideas? I guess this is a very common scenario.
Note: I dont need to search all records. I need to search a specific record. So in the above table, I just need to search one record that has field_id = 1. i.e. (where field_id = 1). (May not matter, but just an info)
Well, this is a good argument for having data in a proper relational form. But, you can try:
select t.*
from t
where (find_in_set($user_input, 1) = 0 or
find_in_set(substring_index(substring_index($user_input, ',', find_in_set($user_input, 1)), ',', -1), matches) > 0) and
(find_in_set($user_input, 2) = 0 or
find_in_set(substring_index(substring_index($user_input, ',', find_in_set($user_input, 2)), ',', -1), matches) > 0) and
. . .
Do this for however many values you might have in the userinput set.
I presume there is no straight solution with MySQL query like Find_In_Set. So I guess I will have to handle this with multiple queries or with Looping.