select locate not working well - mysql

Not sure how to explain this. I have the following sample table
id participants
13 128, 125
18 122, 125
29 182, 125
34 17, 12
38 18, 15
I want to get a count of the messages where 12 is on the right so am using the following query, select count(id) as messages from table where locate (12, participants, 2)
The problem with this query is that it returns all results with 12 e.g. 125, so instead of having one count i have 4 counts which is incorrect. Any suggestions on what query to use?

You can get your result with the help of SUBSTRING_INDEX and ', ' as delimiter:
SELECT * FROM your_table
WHERE
SUBSTRING_INDEX(participants, ', ', -1) = 12;
If you can't be sure about the blank after the comma, you could use
SELECT * FROM your_table
WHERE
TRIM(SUBSTRING_INDEX(participants, ',', -1)) = 12;
instead.
Demo
Note
It would be better not to store delimited lists of values in just one field, if you can. It's asking for trouble and bad performance, because MySQL can't use an index for this kind of condition. It's sound advice of Marc to normalize your tables, be rid of this problem and gain performance by use of an index.

FIND_IN_SET() is used for this kind of thing, but you'll need to strip out the spaces too, since those shouldn't be in there. Here, I used REPLACE() to remove the spaces:
SELECT * FROM example
WHERE FIND_IN_SET('12', REPLACE(participants, ' ', ''))

Related

SQL How to sort by "Ranges"

I am currently using a database with different entries like dates, names, but also one column with time "ranges". This basically means that there can be a definite number like "10" in this cell, but also a value like "10-15" or "5-10".
So what I want to do here is to sort them by an "average" value ((Lowest+Highest)/2). So in case of the 3 mentioned values it should be
5-10
10
10-15
I am wondering if it is possible to embed this into the SQL statement in some way.
And if it is not possible, I'd like to know the easiest way to implement it otherwise.
Right now I am putting the $SQL_statement together via several conditions, then putting everything into $resultset which is then used with "while". Here are some snippets:
$resultset=mysql_query($SQL_statement);
while ($currententry=mysql_fetch_array($resultset))
{
echo $currententry['Platform'];
echo $currententry['PlaytimeInH']."h";
}
You can do this with substring_index() and arithmetic:
order by (substring_index(col, '-', 1) + 0 +
substring_index(col, '-', -1) + 0
) / 2
The division by 2 is unnecessary, but you do specify the average in your question.
Note that the above will work even if col has no hyphen in it.
You could use a select with a case when clause in order by
select col1, col2, cole
from your_table
order by case
when your_column = '5-10' then 1
when your_column = '10-15' then 2
when your_column = '15-20' then 3
else 4
end

MySQL - Return from a string the leftmost characters from 2 different characters

I have a database with some codes seperated by / or -, I want to show the left side only, this is an example of the data:
45/84
12/753
68-53
15742-845
2/556
So, i want to get this:
45
12
68
15742
2
I tried using LEFT(), but this search for 1 character only, and returns a warning if the character is not found, this is what LEFT(field,'/') returns.
45
12
(WARNING)
(WARNING)
2
So, what about a REGEXP?
an IF?
any way to ignore from the first non numeric character?
I dont' have more ideas...
Thank you!
Try this:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(col, '-', 1), '/', 1)
FROM mytable
Demo here
You can do it with this statement. Replace the string '15742/845' with your fieldname
SELECT SUBSTRING_INDEX( REPLACE('15742/845','/','-'), '-', 1)

MySQL sorting with alphanumeric prefix

I've got a database with a column that contains the following data:
aaa-1
aaa-2
aaa-3
...
aaa-10
aaa-11
...
aaa-100
aaa-101
...
aaa-1000
When I query and sort the data in ascending order, I get:
aaa-1
aaa-10
aaa-11
...
aaa-100
aaa-101
...
aaa-1000
...
aaa-2
...
aaa-3
Is this actually the correct (machine) way of sorting? Is the order being screwed up because of the aaa- prefix? How do I go about sorting this the way a human would (ie something that looks like the first snippet)?
P.S. If the problem does lie in the prefix, is there a way to remove it and sort with just the numeric component?
P.P.S. It's been suggested to me that I should just change my data and add leading zeroes like aaa-0001 and aaa-0002, etc. However, I'm loathe to go that method as each time the list goes up an order of 10, I'd have to reformat this column.
Thank you all in advance! :)
You can extract the number part, convert it to numeric data type and then do an ORDER BY:
SELECT mytable.*,
CAST(SUBSTRING_INDEX(mycolumn, '-', - 1) AS UNSIGNED) mycolumnintdata
FROM
mytable
ORDER BY mycolumnintdata;
If there are expressions which does not match number, the CAST function would return 0 and those records would be displayed first. You may handle this separately if needed.
I had a similar issue and the trick that did it for me was this one
*"ORDER BY LENGTH(column_name), column_name
As long as the non-numeric part of the value is the same length, this will sort 1 before 10, 10 before 100, etc."*
as given by Andreas Bergström on this question.
Hope that helps someone.
this is the alphabetical order,
you want numerical order,
for do this you must in the ORDER BY clause
trim the costant "aaa-" part
convert it in number
convert(SUBSTRING(val, 3), integer)
I will give you a sample sorting. Not based on your data sample, but this could help you out.
Say you have data like this :
id
----
1
2
6
10
13
when you do ORDER BY id ASC would return :
id
----
1
10
13
2
6
I suggest, use LPAD.
This query : SELECT LPAD('12',5,'0') return 00012
So when you have table data like I provide above, you can sort them like this :
SELECT * FROM TABLE
ORDER BY LPAD(ID,7,'0') ASC
Based on your data.
SELECT SUBSTR('aaa-100',5,LENGTH('aaa-100') - 3) return 100
So, SELECT LPAD( SUBSTR('aaa-100',5,LENGTH('aaa-100') - 3), 7, '0') return 00000100
So you can combine string function such as SUBSTR and LPAD. Do have any clue now?

ORDER BY FIELD not working - error message

I have this Select:
SELECT pts_name
FROM products_tecspecs
WHERE pts_id IN ( 5275, 21, 5276, 5277,
5278, 49, 5279 )
ORDER BY FIELD (pts_id, 5275, 21, 5276, 5277, 5278, 49, 5279)
I am trying to get the result and order it the way I want. I found this answer but got this error: #1305 - FUNCTION database_name.FIELD does not exist
I am trying to get specifics results with IN (that's working), but sorting the way I want.
Help you be apreciated.
Remove the space between the function and the parenthesis: FIELD (
MySQL parser does not like spaces there. Use:
FIELD(pts_id, ...)
you can also try subquery to order by records in custom order
SELECT pts_name
FROM (SELECT pts_name,
CASE pts_id
WHEN 5275 THEN 1
WHEN 21 THEN 2
WHEN 5276 THEN 3
WHEN 5277 THEN 4
WHEN 5278 THEN 5
WHEN 49 THEN 6
WHEN 5279 THEN 7
END AS sort_order
FROM products_tecspecs
WHERE pts_id IN ( 5275, 21, 5276, 5277, 5278, 49, 5279)
) a
ORDER BY a.sort_order ASC ;

MySQL Logical Operators in a field with text and integers

I have a table that looks like:
ATTRIBUTE1 | ATTRIBUTE2
weight: 190| height: 175
ctr: 400 | dmd: 19
Is it possible to do comparative operations on these fields?
Like, if I wanted to find everyone with a weight less than 200, what would the syntax look like for that? I figure the query would look like the following, if there were no text in the field:
SELECT * FROM mytable WHERE attribute1 < '200'
But since the field has the defining text "weight:", I'm not quite sure how to do this.
Rather
CAST(SUBSTRING(attribute1, INSTR(attribute, ': ') AS SIGNED)
because the value contains the string in the beginning.
Basically you do like this:
Find the index of ': ' and use it as a substring for the value (to skip everything until the actual number). Then you cast it to an Int
(maybe you need to add a +1 to INSTR. I'm not sure since i don't have a mysql client right here
where cast(substring(ATTRIBUTE1, instr(ATTRIBUTE1, ': ')+1 ) as unsigned) <200
alternative:
where cast(replace(Field_2, 'weight: ', '') as unsigned) > 180