Get unique values from MySql - mysql

In my table are values like: 14, 15, 14, R14, R15, R15C, R14C,....
With current distinct mode I get: 14, R14, R14C, R15, R15C,...
But what I want is only unique numbers like this: 14, 15,...
To get rid of letters and get unique numbers only?
My current code:
SELECT DISTINCT diameter FROM tires WHERE category = '$cat' ORDER BY diameter ASC

SELECT DISTINCT 0 + REGEXP_REPLACE(diameter, '^[[:alpha:]]*', '') diameter
FROM tires;
Regular expression removes all letter chars from the beginning, then the value is implicitly converted to numeric by adding zero (by fact - trailing letters are removed).
fiddle
I forget to tell that I have decimal values like R22,5 - RoX
Replace comma with dot before or after REGEXP_REPLACE(), but before adding zero. For example,
SELECT DISTINCT 0 + REGEXP_REPLACE(REPLACE(diameter, ',', '.'), '^[[:alpha:]]*', '') diameter
FROM tires;
fiddle
PS. I'd recommend to add generated column to the table structure. See example.

Related

How to natural sort “X-Y” string data, first by X and then by Y?

Given this data:
W18-40461
W19-1040
W20-4617
W20-100
I've tried several of the common natural sorting methods for mysql, but they won't sort these in a natural descending way, like:
W20-4617
W20-100
W19-1040
W18-40461
For example:
select theID
from Table
where theID
order by lpad(theID, 9, 0) desc
Assuming the parts on either side of the - are limited to 2 digits and 5 digits respectively, you can extract the two numeric values using SUBSTR (and LOCATE to find the - between the two numbers) and then LPAD to pad each of those values out to 2 and 5 digits to allow them to be sorted numerically:
SELECT *
FROM data
ORDER BY LPAD(SUBSTR(id, 2, LOCATE('-', id) - 2), 2, '0') DESC,
LPAD(SUBSTR(id, LOCATE('-', id) + 1), 5, '0') DESC
Output (for my expanded sample):
id
W20-12457
W20-4617
W20-100
W19-1040
W18-40461
W4-2017
Demo on db-fiddle
If the values can have more than 2 or 5 digits respectively, just change the second parameters to LPAD to suit.
I would do this as:
order by substring_index(col, '-', 1) desc,
substring_index(col, '-', -1) + 0 desc
This orders by the part before the hyphen as a string. And it converts the part after the hyphen to a number for sorting purposes.

sql - Add 0 after a numeric value

I have columns in my sql table. I am wondering how can I add zero after numeric values in my columns. So for example:
I have values e.g 9, 2, 7, 10. I want to add a zero after these numbers. I want them to be 90, 20, 70, 100.
There are some values in the columns that already have 0s after them e.g 70, 20, 100. These ones should retain their values.
How do I go about this?
Just multiple the column by ten (not sure what your table name is, edit that query):
UPDATE __TABLE__
SET mt_ca1 = (mt_ca1 * 10),
mt_ca2 = (mt_ca2 * 10)
WHERE mt_ca1 < 100 OR mt_ca2 < 100;
It is not clear if you want to add zeroes after only double-digit numbers or all numbers. MySQL has substring functionality though you'd need to clarify your needs.
You can use CONCAT and CASE
assuming the column type is INT
use CASE to check if the value multiplied to 10 is less than or equal to 100.
SELECT
(CASE
WHEN (mt_ca1*10) <= 100
THEN CONVERT(CONCAT(mt_ca1,'0'),UNSIGNED INTEGER)
ELSE mt_ca1
END) AS mt_ca1
FROM yourtable

Split value and place separated value into two different column using mysql

I want to split two values which is separated by multiplication symbol for example "12X36" after split it should get 12 in one column 36 in one column i.e 'X' symbol removed from those numbers get get final values in separate column for every record in Mysql
SELECT SUBSTRING_INDEX('12X36','X',2)
but this is eliminating 'X', I want to show 12 in separate column and 36 in separate column but don't know further step
expected output:
1) 12X36
2) 23X40
column1 column2
12 36
23 40
getting output
SUBSTRING_INDEX('12X36','X',2)
12
As mentioned, many ways. Here is one using LEFT and RIGHT
SELECT LEFT('12X36', LOCATE('X', '12X36') - 1), RIGHT('12X36', LOCATE('X', '12X36') - 1)
and one using reg exp, here the substrings are all digits from the start (denoted by ^) up to a non-digit and all digit between the last noon-digit and the end of the string (indented by $)
SELECT REGEXP_SUBSTR('12X36', '^[0-9]*'), REGEXP_SUBSTR('12X36', '[0-9]*$')
There are numerous ways. One is to locate() the 'X' and substring() around it.
SELECT substring('12X36', 1, locate('X', '12X36') - 1),
substring('12X36', locate('X', '12X36') + 1)

How to exclude non-numeric column results from MySQL query?

I have a column, called value, that includes strings as well as numbers as data, eg:
contentid, value
16, 200
18, 150
47, Foo
16, Red
16, 50
18, GREEN
I need a way to retrieve only the results that are actual numbers (and, additionally, that are <= 180).
The expected results from above should be: 18, 150 and 16, 50 but I am getting results with strings as well.
I have tried this from other SO questions:
SELECT *
FROM `contentvalues`
WHERE (
contentid =16
OR contentid =18
)
AND `value` <= 180
AND value NOT LIKE '%[a-z0-9]%'
But this has not worked.
Would anyone be able to point me in the right direction?
According to this:
... AND value REGEXP ('[0-9]')
... but someone's blog is never the best source. Actually that matches everything that contains a number. Better would be
... AND value REGEXP ('^[0-9]+$')
Above regex is
^ "From the begining of the string..."
[0-9] "There should be a number..."
+ "actually exactly 1 or more of those numbers"
$ "and the the string should just end."
Here is a solution which does not require the REGEXP() function, which may not available in all RDBMS:
SELECT *
FROM `contentvalues`
WHERE (contentid = 16 OR contentid =18)
AND concat('',value * 1) = value
This will work as long as the numbers in the value column do not appear in scientific notation, with trailing decimals, or other weird formats. Read this SO article for more information.

MySQL sorting product codes that have both alpha and numeric characters

I have to sort output of a query for product names where the names have both alpha and numeric characters.
I have already found various solutions that convert the variables to numeric values (+0, etc.), and they sort the numeric part of the product names. But the preceding part of the product name string is of varying lengths, so the names aren't sorted alphabetically:
Post Lantern PL1
Post Lantern PL2
Post Lantern PL10
Post Lantern PL22
Landscape Light LV1
Landscape Light LV2
Landscape Light LV10
Landscape Light LV11
I guess the shorter names are sorted first?
I want the results sorted naturally: alphabetically, with the numbers in a natural order as well. I have tried:
ORDER by CAST(`product_name` AS DECIMAL), product_name
...
ORDER by product_name+0
The shorter names get sorted first, even though they are later in the alphabet. The numbers in the last part need to be in numerical order.
Here's a long query doing what you're looking for. I'm not sure about performance, though. You might also want to make some tests on several records to make sure.
SELECT
*
,SUBSTRING(
REVERSE(CAST(REVERSE(CONCAT(`product_name`,'8')) AS UNSIGNED)),1,
CHARACTER_LENGTH(
REVERSE(CAST(REVERSE(CONCAT(`product_name`,'8')) AS UNSIGNED))
)-1
) AS 'numericVal'
FROM `some_table`
ORDER BY
SUBSTRING(`product_name`,1,CHAR_LENGTH(`product_name`)-CHAR_LENGTH(`numericVal`)),
CAST(`numericVal` AS UNSIGNED INTEGER)
The 8's in the CONCAT() functions are there for numbers that end with zero(s). Otherwise when you reverse e.g. the string "etc30" and parse the number there it will be 3, not 03. So reversing it back will again produce 3 instead of 30.
You can change those two 8's in the CONCAT() functions with any single digit(s) (except zeros) you like.
[EDIT 2]
Here's the breakdown.
# Example record "Post Lantern PL10"...
SELECT
*
,SUBSTRING( # 5a) substring of this is calculated
REVERSE( # 4) gets re-reversed into "108"
CAST( # 3) gets casted into an integer so "801" part is parsed
REVERSE( # 2) gets reversed: "801LP nretnaL tsoP"
CONCAT(`product_name`,'8') # 1) is concatenated with an 8: "Post Lantern PL108"
)
AS UNSIGNED)
),
1, # 5b) from the first character (index is 1 for this in SQL)
CHARACTER_LENGTH( # 5c) and the length is recalculated (steps 1-4 repeated)
REVERSE(
CAST(
REVERSE(
CONCAT(`product_name`,'8')
)
AS UNSIGNED)
)
)-1 # 5d1) minus 1 because at the beginning we appended an 8 and we
# 5d2) want to get rid of it now, so we're dropping the last digit
) AS 'numericVal'
FROM `some_table`
ORDER BY # 6) order by
SUBSTRING(`product_name`, # 7a) first, substring `product_name`
1, # 7b) from the first character
CHAR_LENGTH(`product_name`)-CHAR_LENGTH(`numericVal`) # 7c) with the total length - length of numeric part
),
CAST(`numericVal` AS UNSIGNED INTEGER) # 8a) then, by the numeric part, which gets casted into
# 8b) an integer for accurate numeric ordering
[EDIT 1]
I think the best shot you have (to have total control over the varying data) is to separate product_name into 3 columns - product_name (like "Landscape Light"), product_class (or whatever, like "LV") and product_version (the numeric part).