I have a series of varchar fields in a MySQL database that are "numbered":
+-----------+
| name |
+-----------+
| thing 1 |
| thing 2 |
| thing 3 |
| ... |
| thing 10 |
| thing 11 |
+-----------+
I want to order them as listed above. However, a simple ORDER_BY table.name produces something like the following:
thing 1
thing 10
thing 11
thing 2
thing 3
...
This makes some sense, since MySQL is treating the entire field as a String (varchar). However, I've tried numerous methods to sort including CAST(name AS DECIMAL) and name + 0. This will only sort by the decimal part, ignoring the string part. None of these work because I need to sort by name first and then sort by the trailing decimal.
I tried ORDER_BY name, name + 0, but nothing seems to work. How do I perform and ORDER_BY and then ORDER_BY within that subset? (I think that will work).
You need to have two sorts - first by the name part, and second by the numeric part, like this:
order by left(name,instr(name,' ')),cast(right(name,instr(name,' ')+1) as decimal)
The function SUBSTRING_INDEX can split the string.
SELECT SUBSTRING_INDEX(name, ' ', 1) AS a, CAST(SUBSTRING(name, ' ', -1) AS DECIMAL) AS b
FROM t
ORDER BY a, b
Related
I came across an old post and tried the code with a project that I am working on, and it worked, but I am still confused as to why, could anyone here please unpack the logic behind the code here? I am specifically referring to this fiddle.
I understand substring_index, but not sure what "numbers" does, as well as the char length calculations.
Thanks in advance.
The numbers table is a way to create an ad hoc table that consists of sequential integers.
mysql> SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4;
+---+
| n |
+---+
| 1 |
| 2 |
| 3 |
| 4 |
+---+
These numbers are used to extract the N'th word from the comma-separated string. It's just a guess that 4 is enough to account for the number of words in the string.
The CHAR_LENGTH() expression is a tricky way to count the words in the command-separated string. The number of commas determines the number of words. So if you compare the length of the string to the length of that string with commas removed, it tells you the number of commas, and therefore the number of words.
mysql> set #string = 'a,b,c,d,e,f';
mysql> select char_length(#string) - char_length(replace(#string, ',', '')) + 1 as word_count;
+------------+
| word_count |
+------------+
| 6 |
+------------+
Confusing code like this is one of the many reasons it's a bad idea to store data in comma-separated strings.
I am looking to find out if there is a way to count the number of trailing zeros in a column. The column is made up of a maximum of 13 numbers as shown below and I want to count all the zeros before an actual number but not sure how to go about doing this.
Example numbers
2200040000000 -- this would have the value 7
1411258181000 -- this would have the value 3
I have managed to do this in Excel but I am trying to do this directly in MySQL in a query rather than importing the data in Excel and then writing the query as theres more steps to go through.
The following is the formula:
=6+RIGHT(TEXT(B17,"0.##############E+00"),2)-LEN(TEXT(B17,"0.##############E+00"))
I would really appreciate it, if somebody could advise on how I could resolve this issue as would really help me to move forward and not go back and forth with Excel.
You could use string function TRIM(), which is available since the early days of MySQL:
char_length(num) - char_length(trim(trailing '0' from num))
trim(...) removes trailing 0s from the string; the difference of lengh between the original value and the trimed value gives you the number of trailing 0s in the string.
Demo on DB Fiddle:
create table t (num bigint);
insert into t values (2200040000000), (1411258181000);
select
num,
char_length(num) - char_length(trim(trailing '0' from num)) cnt_trailing_0s
from t;
num | cnt_trailing_0s
------------: | --------------:
2200040000000 | 7
1411258181000 | 3
You can do it with reverse() like this:
select col,
length(col) - length(reverse(col) + 0) trailing_zeros
from tablename
replace col with the actual name of the column.
If there is a case of the column to contain only zeros then use this:
length(col) - length(reverse(col) + 0) + (col = 0)
See the demo.
Results:
| col | trailing_zeros |
| ------------- | -------------- |
| 2200040000000 | 7 |
| 1411258181000 | 3 |
I'm working with a MySQL database that contains a substantial amount of data (about 10.000 records). The data in the database is logging of a machine maintenance, one of the fields contains a basic timeline (just steps that are timestamped) explaining all the work done. In this field I'm looking for certain strings that can indicate certain procedures (i.e. ABC123.ABC, abc111.abc, abc001.abc).
I'm looking for matches in this field with pattern matching like such
SELECT * FROM [tablename]
WHERE `work_performed` LIKE '% ______.___ %'
ORDER BY id DESC;`
The regex is very general but I can specify that further myself.
However, since the field which contains the string I'm looking for can be very large (up to 2364763 characters) i want to return the records matching the pattern specified but I also want to return a field that contains just the matched expression so I can confirm it is actually what I'm looking for and can use that string further.
I have found people with the same issue but I cannot reproduce their results.
Something like this might work?:
SELECT *, SUBSTRING(`work_performed`,
patindex('%[0-9][0-9][0-9]%', `work_performed`)-1, 5) as match
FROM [tablename]
WHERE `work_performed`LIKE '% ______.___ %'
I would like to get output that looks somewhat like this:
+----+-------------------------------------------+------------+
| id | work_performed | match |
+----+-------------------------------------------+------------+
| 1 | 2017-02-26|10:59| Arrival: admin1 | ABCD12.adb |
| | 2017-02-26|10:59| diagnosed error ab-0001 | |
| | 2017-02-26|11:02| ran ABCD12.adb | |
| | 2017-02-26|11:03| system back online | |
+----+-------------------------------------------+------------+
| 2 | 2017-02-26|10:59| Arrival: admin34 | abc123.ags |
| | 2017-02-26|10:59| diagnosed error WP1234 | |
| | 2017-02-26|11:02| ran abc123.ags | |
| | 2017-02-26|11:03| system back online | |
+----+-------------------------------------------+------------+
I apologise if I didn't give enough details but I'm an intern at a major company and we have very strict rules about confidentiality.
If there is a need for any additional information I will try to.
EDIT
I have been trying to search for the string I'm looking for with regexp, but I cant get it to work as I want to, here is what I tried:
SELECT * FROM tablename
WHERE `work_performed` regexp '% ([a-z]^3)([0-9]^3).([a-z]^3) %'
ORDER BY id DESC;
The solution using CONCAT, SUBSTR, SUBSTRING_INDEX and LOCATE functions:
SELECT
CONCAT(SUBSTRING_INDEX(SUBSTRING_INDEX(work_performed, '.', 1), ' ', - 1),
'.',
SUBSTR(SUBSTRING_INDEX(work_performed, '.', - 1), 1,
LOCATE(' ', SUBSTRING_INDEX(work_performed, '.', - 1))
)
) m
FROM
tablename
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html
DEMO link
In a MySQL-table I have a VARCHAR-column with different values, which may represent String-, Integer-, Float-, Whatever-Values. These Values are written as a language-specific String into the Database, this means a float-value of 123.45 may be written as a String like "123,45" in german language (using VB.Net...)
As I need average values of float-values wich are in the same group:
How can I cast such a string to a FLOAT within MySQL?
Simply AVG(CONVERT(value, DECIMAL)) won't work (returns 99.00000), conversion to FLOAT is not possible.
Charset is utf8, Collation is utf8_general_ci.
Sample table:
id | value | group
1 | 122,45 | 1
2 | 66,34 | 1
3 | blabla | 2
4 | 109,21 | 1
5 | bababa | 2
Goal: somethig like SELECT AVG(CONVERT(value, DECIMAL)) FROM table WHERE (group=1) should result in 99.333333, not 99.
Any Ideas?
Christoph
PS.: I did not make that database-layout...
You could try
SELECT AVG(CONVERT(
REPLACE(REPLACE(value, '.', ''), ',', '.'),
DECIMAL(10,2)))
FROM `table`
WHERE `group`=1
The string function format(x,d,locale) should do exactly what you want. See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_format
In a MySQL-table I have a VARCHAR-column with different values, which may represent String-, Integer-, Float-, Whatever-Values. These Values are written as a language-specific String into the Database, this means a float-value of 123.45 may be written as a String like "123,45" in german language (using VB.Net...)
As I need average values of float-values wich are in the same group:
How can I cast such a string to a FLOAT within MySQL?
Simply AVG(CONVERT(value, DECIMAL)) won't work (returns 99.00000), conversion to FLOAT is not possible.
Charset is utf8, Collation is utf8_general_ci.
Sample table:
id | value | group
1 | 122,45 | 1
2 | 66,34 | 1
3 | blabla | 2
4 | 109,21 | 1
5 | bababa | 2
Goal: somethig like SELECT AVG(CONVERT(value, DECIMAL)) FROM table WHERE (group=1) should result in 99.333333, not 99.
Any Ideas?
Christoph
PS.: I did not make that database-layout...
You could try
SELECT AVG(CONVERT(
REPLACE(REPLACE(value, '.', ''), ',', '.'),
DECIMAL(10,2)))
FROM `table`
WHERE `group`=1
The string function format(x,d,locale) should do exactly what you want. See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_format