mysql natural sort - mysql

I have example number in the format :
1.1
1.1.4
1.1.5
2.1
2.1.10
2.1.23
3.1a
3.1b
4.1.5
4.2.6
4.7.12
How do I sort it in MySQL ? I can do that easily from the $sort command line option but nothing seems to work in MySQL

It may work if you split the string into pieces and order by each relevant piece.
SELECT data
FROM example
ORDER BY
CAST(SUBSTRING_INDEX(data, '.', 1) AS BINARY) ASC,
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data , '.', 2), '.', -1) AS BINARY) ASC,
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data , '.', -1), '.', 1) AS BINARY) ASC;
Can't say I support doing something like that in MySQL, but I guess it would get you where you need to be, at least with my test data. Just remember you'll need to edit the number if you change the number of elements in the string.

Try ordering by INET_ATON (for MySQL 3.23.15 and newer)
ORDER BY INET_ATON(some_field);
PS. It works for IP addresses, don't know how it handle letters

Was there something wrong with ORDER BY?
I tried:
CREATE TABLE example (data VARCHAR(30));
INSERT INTO example VALUES ('4.2.6'), ('1.1.5'), ('2.1.10'), ('3.1b'), ('2.1'), ('4.7.12'), ('1.1'), ('2.1.23'), ('1.1.4'), ('3.1a'), ('4.1.5');
SELECT * FROM example ORDER BY data;
... and it seemed to work as you'd like. (I can't guarantee that there isn't some corner case where your real data might not ordered by what you'd consider "natural." That seems to be a heuristic term rather than a precisely defined term of art.

Related

How to pass multiple delimeters in substring_index

I want to query the string between https:// or http:// and the first delimeter characters that comes after it. For example, if the field contains:
https://google.com/en/
https://www.yahoo.com?en/
I want to get:
google.com
www.yahoo.com
My initial query that will capture the / only contains two substring_index as follows:
SELECT substring_index(substring_index(mycol,'/',3),'://',-1)
FROM mytable;
Now I found that the URLs may contain multiple delimeters. I want my statament to capture multiple delimeters possibilities which are (each one is a separate character):
:/?#[]#!$&'()*+,;=
How to do this in my statement? I tried this solution but the end result the command could not be executed due to syntax error while I am sure I followed the solution. Can anyone help me correctly construct the query to capture all the delimeter characters I listed above?
I use MySQL workbecnh 6.3 on Ubuntu 18.04.
EDIT:
Some corrections made in the first example of URLs.
First, note that https://www.yahoo.com?en/ seems like an unlikely URL, because it has a path separator contained inside the query string. In any case, if you are using MySQL 8+, then consider using its regex functionality. The REGEXP_REPLACE function can be helpful here, using the following pattern:
https?://([A-Za-z_0-9.-]+).*
Sample query:
WITH yourTable AS (
SELECT 'https://www.yahoo.com?en/' AS url UNION ALL
SELECT 'no match'
)
SELECT
REGEXP_REPLACE(url, 'https?://([A-Za-z_0-9.-]+).*', '$1') AS url
FROM yourTable
WHERE url REGEXP 'https?://[^/]+';
Demo
The term $1 refers to the first capture group in the regex pattern. An explicit capture group is denoted by a quantity in parentheses. In this case, here is the capture group (highlighted below):
https?://([A-Za-z_0-9.-]+).*
^^^^^^^^^^^^^^^
That is, the capture group is the first portion of the URL path, including domain, subdomain, etc.
In MySQL 8+, this should work:
SELECT regexp_replace(regexp_substr(mycol, '://[a-zA-Z0-9_.]+[/:?]'), '[^a-zA-Z0-9_.]', '')
FROM (SELECT 'https://google.com/en' as mycol union all
SELECT 'https://www.yahoo.com?en'
) x
In older versions, this is much more challenging because there is no way to search for a string class.
One brute force method is:
select (case when substring_index(mycol, '://', -1) like '%/%'
then substring_index(substring_index(mycol, '://', -1), '/', 1)
when substring_index(mycol, '://', -1) like '%?%'
then substring_index(substring_index(mycol, '://', -1), '?', 1)
. . . -- and so on for each character
else substring_index(mycol, '://', -1)
end) as what_you_want
The [a-zA-Z0-9_.] is intended to be something like the valid character class for your domain names.

Capture a number in a string

I store a serialized table in a Mysql column. The data looks like this:
a:2:{i:116;s:1:"4";i:113;s:1:"6";}
I'm trying to extract the number that's always placed before ;s:1:"6";
In the example above, the number would be 113.
I'm running Mysql 5.7, so I don't have access to new regex functions. It would have been nice to access PREG_CAPTURE and just write
PREG_CAPTURE(\'i:([0-9]+);s:1:"6";\', mycolumn, 1)
But I can't use PREG_CAPTURE and I'm stuck. Any idea?
Use substring_index.
Try this
SELECT SUBSTRING_INDEX( field1, ';s:1:"6";',1 )

MySql : query to format a specific column in database table

I have one column name phone_number in the database table.Right now the numbers stored in the table are format like ex.+91-852-9689568.I want to format it and just want only digits.
How can i do it in MySql ? I have tried it with using functions like REGEXP but it displays error like function does not exist.And i don't want to use multiple REPLACE.
One of the options is to use mySql substring. (As long as the format doesn't change)
SELECT concat(SUBSTRING(pNo,2,2), SUBSTRING(pNo,5,3), SUBSTRING(pNo,9,7));
if you want to format via projection only, use SELECT, you will only need to use replace twice and no problem with that.
SELECT REPLACE(REPLACE(columnNAme, '-', ''), '+', '')
FROM tableName
otherwise, if you want to update the value permanently, use UPDATE
UPDATE tableName
SET columnName = REPLACE(REPLACE(columnNAme, '-', ''), '+', '')
MySQL does not have a builtin function for pattern-matching and replace.
You'll be better off fetching the whole string back to your application, and then using a more flexible string-manipulation function on it. For instance, preg_replace() in PHP.
Try the following and comment please.
Select dbo.Regex('\d+',pNo);
Select dbo.Regex('[0-9]+',pNo);
Reference on RUBLAR.
So MYSQL is not like Oracle, hence you may just use a USer defined Function to get numbers. This could get you going.

Select distinct records based on regexp pattern

I have a db with domains.
I need to pull the domains suffixes and create a list of those suffixes. (.com, .net, .org ...)
I've found that regexp patterns may help me. The only thing I can't make is to filter those domains based on the pattern + uniqueness, in order to get my list.
Here's my query:
$qry="select * from domain where domain_name REGEXP '[[.period.]][a-z]+'";
How should I add the unique criteria to it?
Thank you.
UPDATE:
Here's the working query:
SELECT DISTINCT SUBSTRING_INDEX(domain_name, '.', -1) FROM domains WHERE domain_name REGEXP '[[.period.]][a-z]+'
MySQL has no construct to substitute using regular expressions, or to access matching groups. So regular expressions likely won't help you. Perhaps the SUBSTRING_INDEX function is more useful for you, as you can use that to extract the part after the final dot, using
SUBSTRING_INDEX(domain_name, '.', -1) AS tld

Extract Only charcters from a String

I have a column value like
lut00006300.txt
sand2a0000300.raw
I need to extract only character data from above given column values. I tried the below query and was able to get the first three characters.
select filesize,
substring(Filename FROM 1 FOR 3) AS Instrument from Collection;
Is there any approach to extract only the characters from the column value leaving the extensions
The results should be :
LUT
SAND2A
I think below query will helps you.
select filesize,Filename from Collection where Filename REGEXP '[:alpha]';
Refer:- http://dev.mysql.com/doc/refman/5.1/en/regexp.html
SELECT
filesize,
UPPER(SUBSTRING_INDEX(SUBSTRING_INDEX(Filename, '.', 1), '0', 1)) AS Instrument
FROM Collection;
This is a dirty solution, since you want to have the 2 in SAND2A.
Read more about the functions here.