Extract a set of digits from a string column in MySQL - mysql

I am trying to extract a fixed-length digits from a string column in MySQL, how can I go about doing so? The usual like and regexp doesn't work, so am pretty certain a function is needed, but unsure where to start and how to go about writing one.
Please advise.
The fixed-length digits are 10 digits and a sample of the string column:
'SGD0.00 AUTOMSG:'0179187381' is near Esso # 23:59.'
Please be advised the location of the 10 digits in the string varies.

Simple:
Just use: SUBSTR(str,x,y)
where:- str -> String,
x -> position,
y -> length
Example: SELECT SUBSTR('ABCDEFG',2,3); -> BCD
For more information visit this link:
http://www.w3resource.com/mysql/string-functions/mysql-substring-function.php

mysql> select substr("'SGD0.00 AUTOMSG:'0179187381' is near Esso # 23:59.'", 19,10);
+-----------------------------------------------------------------------+
| substr("'SGD0.00 AUTOMSG:'0179187381' is near Esso # 23:59.'", 19,10) |
+-----------------------------------------------------------------------+
| 0179187381 |
+-----------------------------------------------------------------------+
1 row in set (0.48 sec)

you may try like this:
SELECT SUBSTRING('Quadratically',5);
Syntax: SUBSTRING(str,pos)
For more info: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring

If the 10 digit number will always be preceeded with :' then you could use:
select substr(column_name, locate(":'", column_name) + 2, 10) from table_name
(assuming :' does not appear anywhere else before the number in the string)

Related

Compairing two strings in MYSQL

I have a sequence of 20 numbers from 0 to 2, I want to compare this string with other sequences saved in my database, the problem is that the lenght of the strings saved on the database fluctuates.Also the comparison needs to be done from the end to the start.
Example of what I want:
20 digits string:
'1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1'
couple of strings saved in the database:
1 - '1,1,2,1'
2 - '2,1,2,2,2,2'
3 - '2,1'
4 - '1,1,2,1,2,1'
In this case the query would return the 1 and 3 only
create table mytable ( s varchar(60) );
insert into mytable values
('1,1,2,1'),
('2,1,2,2,2,2'),
('2,1'),
('1,1,2,1,2,1');
set #x = '1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1';
select s from mytable
where right(#x, length(s)) = s;
Output:
s
1,1,2,1
2,1
Fiddle: https://www.db-fiddle.com/f/r5m2hPbnmUu5VQfYvMVtir/0
You could use a LIKE trick here. For example, to check for the first string 1,1,2,1:
SELECT *
FROM yourTable
WHERE ',1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1,' LIKE '%,1,1,2,1,%';

Return strings which contains number on specific position

I am basic on SQL queries and I need some help.
I have to select all string values which contains number e.g. 7 only on specific position in that string.
For example:
I have string: 987654321 and if on position 3 I will have number 7, then it should be selected.
So in example this string will be selected, because on 3rd position I have number 7.
Is there any SQL function for that, or something which could help me?
EDIT:
Example table
TABLE
Numbers Value
987654321 1
123456789 2
789009871 3
654321092 4
847949372 5
Output:
TABLE
Numbers Value
987654321 1
847949372 5
Statement:
SELECT table.numbers
FROM TABLE
WHERE substr(table.numbers,3,1)='7' <--- what to do here? --->
Many thanks in advance.
For a regex option, you may use MySQL's REGEXP operator:
SELECT *
FROM yourTable
WHERE num REGEXP '^[0-9]{2}7';
On Oracle, you could use REGEXP_LIKE:
SELECT *
FROM yourTable
WHERE REGEXP_LIKE(num, '^[0-9]{2}7');
You should use case statement.
select case when substr(stringcol, 3,1) = '7' then stringcol else "not valid" end as stringcol from <Table Name>

MYSQL : Find the last occurrence of a character in a string

Length will be dynamic and i want to find the data before last occurrence of a character in a string in MYSQL
Like strrchr in php
To get last occurrence of _ (underscore) I need to pass length. and here it's 3
mysql> SELECT SUBSTRING_INDEX ('this_is_something_here', '_', 3);
+----------------------------------------------------+
| SUBSTRING_INDEX ('this_is_something_here', '_', 3) |
+----------------------------------------------------+
| this_is_something |
+----------------------------------------------------+
And here, to get last occurrence of _ (underscore) i need to pass length. and here it's 6
mysql> SELECT SUBSTRING_INDEX ('and_this_may_go_like_this_too', '_', 6);
+-----------------------------------------------------------+
| SUBSTRING_INDEX ('and_this_may_go_like_this_too', '_', 6) |
+-----------------------------------------------------------+
| and_this_may_go_like_this |
+-----------------------------------------------------------+
i want data string before last occurrence of _ (underscore) just shown in above example but without passing length.
Note : from above example i want before data of "_here" and "_too"
last occurrence of _ (underscore)
Is there any built-in functionality to achieve this in MySQL?
Thanks in advance amigos.
I didn't quite get your examples, but I think what you want is to pass -1 as the length and prepend the substring prior.
Compare
strrchr('and_this_may_go_like_this_too', '_'); // Returns _too
SELECT SUBSTRING_INDEX('and_this_may_go_like_this_too', '_', -1);
-- Returns too, just need to concatenate `_` so...
SELECT CONCAT('_', SUBSTRING_INDEX('and_this_may_go_like_this_too', '_', -1));
-- Returns _too
If you're looking for the part of the string before and up to the needle, and not from the needle to the end of the string, you can use:
SET #FULL_STRING = 'this_is_something_here';
SELECT LEFT(#FULL_STRING, LENGTH(#FULL_STRING) - LOCATE('_', REVERSE(#FULL_STRING)));
-- Returns this_is_something
Note that the second statement is not what strrchr does.
select reverse(substr(reverse('this_is_something_here'), 1+locate('_', reverse('this_is_something_here'))));
Use reverse, locate, right then replace without using length
Set #str = 'there_is_something';
Select replace(#str,right(#str,locate('_',reverse(#str))),'');
You can write query like this
SELECT SUBSTRING_INDEX('and_this_may_go_like_this_too','_',(LENGTH('and_this_may_go_like_this_too')-LENGTH(REPLACE('and_this_may_go_like_this_too' ,'_',''))) - 1);

How to: Select from MYSQL text field type only the numbers that start with 89 using REGEXP?

I have tried in many ways to select from text fields only the numbers that start with 89. I don't have a fix length after the first 2 numbers.
How can I do this to work properly and not get numbers like 389xxxxxx in results, for example. THE minimum length should be at least 8 characters.
Thank you!
If your column is integer, then you can probably do something like:
select * from my_table where cast(int_column) as char) like '89______%'
(that's 6 underscore characters before the percentage char)
If it's character value, then you can do this:
SELECT * FROM mytable WHERE char_column REGEXP "^89[[:digit:]]{6,}$"
If your column is numeric with decimal places and you want only integer values, then you need to do something like
SELECT * FROM mytable WHERE cast(numeric_column as char) REGEXP "^89[[:digit:]]{6,}$"
Edit: It seems Tim has edited his answer, which I referred to, so I edited my answer to include his code for column of character type.
SELECT * FROM foo WHERE bar REGEXP "([^0-9]89[0-9]*)|(^89[0-9]*)"
SELECT * FROM mytable WHERE mycolumn REGEXP "(^|[^[:digit:]])89[[:digit:]]{6,}";
will do this:
( # Either match
^ # the start of the string
| # or
[^[:digit:]] # any character except a digit
) # End of alternation.
89 # Match 89
[[:digit:]]{6,} # plus at least 6 more digits.

CAST DECIMAL to INT

I'm trying to do this:
SELECT CAST(columnName AS INT), moreColumns, etc
FROM myTable
WHERE ...
I've looked at the help FAQs here: http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html , it says I can do it like CAST(val AS TYPE), but it's not working.
Trying to convert a decimal to int, real value is 223.00 and I want 223
You could try the FLOOR function like this:
SELECT FLOOR(columnName), moreColumns, etc
FROM myTable
WHERE ...
You could also try the FORMAT function, provided you know the decimal places can be omitted:
SELECT FORMAT(columnName,0), moreColumns, etc
FROM myTable
WHERE ...
You could combine the two functions
SELECT FORMAT(FLOOR(columnName),0), moreColumns, etc
FROM myTable
WHERE ...
A more optimized way in mysql for this purpose*:
SELECT columnName DIV 1 AS columnName, moreColumns, etc
FROM myTable
WHERE ...
Using DIV 1 is a huge speed improvement over FLOOR, not to mention string based functions like FORMAT
(graphic from Roland Bouman's blog)
mysql> SELECT BENCHMARK(10000000,1234567 DIV 7) ;
+-----------------------------------+
| BENCHMARK(10000000,1234567 DIV 7) |
+-----------------------------------+
| 0 |
+-----------------------------------+
1 row in set (0.83 sec)
mysql> SELECT BENCHMARK(10000000,1234567 / 7) ;
+---------------------------------+
| BENCHMARK(10000000,1234567 / 7) |
+---------------------------------+
| 0 |
+---------------------------------+
1 row in set (7.26 sec)
mysql> SELECT BENCHMARK(10000000,FLOOR(1234567 / 7)) ;
+----------------------------------------+
| BENCHMARK(10000000,FLOOR(1234567 / 7)) |
+----------------------------------------+
| 0 |
+----------------------------------------+
1 row in set (8.80 sec)
(*) NOTE: As pointed by Grbts, be aware of the behaviour of DIV 1 when used with non unsigned/positive values.
From the article you linked to:
The type can be one of the following values:
BINARY[(N)]
CHAR[(N)]
DATE
DATETIME
DECIMAL[(M[,D])]
SIGNED [INTEGER]
TIME
UNSIGNED [INTEGER]
Try SIGNED instead of INT
The CAST() function does not support the "official" data type "INT" in MySQL, it's not in the list of supported types. With MySQL, "SIGNED" (or "UNSIGNED") could be used instead:
CAST(columnName AS SIGNED)
However, this seems to be MySQL-specific (not standardized), so it may not work with other databases. At least this document (Second Informal Review Draft) ISO/IEC 9075:1992, Database does not list "SIGNED"/"UNSIGNED" in section 4.4 Numbers.
But DECIMAL is both standardized and supported by MySQL, so the following should work for MySQL (tested) and other databases:
CAST(columnName AS DECIMAL(0))
According to the MySQL docs:
If the scale is 0, DECIMAL values contain no decimal point or
fractional part.
use this
mysql> SELECT TRUNCATE(223.69, 0);
> 223
Here's a link
There is an important difference between floor() and DIV 1. For negative numbers, they behave differently. DIV 1 returns the integer part (as cast as signed does), while floor(x) returns "the largest integer value not greater than x" (from the manual). So : select floor(-1.1) results in -2, while select -1.1 div 1 results in -1
your can try this :
SELECT columnName1, CAST(columnName2 AS SIGNED ) FROM tableName
There's also ROUND() if your numbers don't necessarily always end with .00. ROUND(20.6) will give 21, and ROUND(20.4) will give 20.
Try cast (columnName as unsigned)
unsigned is positive value only
If you want to include negative value, then cast (columnName as signed),
The difference between sign (negative include) and unsigned (twice the size of sign, but non-negative)
1 cent:
no space b/w CAST and (expression).
i.e., CAST(columnName AS SIGNED).