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

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.

Related

Why we use in & in mysql query condition?

One of guys share me a query but still i am not undestand what is mean. Any one have idea why we use "&" in mysql query.
It also return result but don't know what condition is applying.
It is a bitwise logical AND operator.
The operator & is the bitwise AND operator for MySql.
...why we are use "&" in for condition
Your question is application specific and can't be answered without knowing the requirement.
The binary representation of 30 is 00011110.
As you can see this number has the bits 2 to 5 (starting from right) set (=1).
Any integer number, like entity_id, when written in binary, that has any of these bits set when used in the operation entity_id & 30 would return a non-zero value.
For example when entity_id = 12, then entity_id in binary is 00001100 and:
00001100(=12) & 00011110(=30) = 00001100(=12)
which is non-zero value interpreted as TRUE in the WHERE clause.
But when entity_id = 129, then entity_id in binary is 10000001 and:
10000001(=129) & 00011110(=30) = 00000000(=0)
which is 0 and it is interpreted as FALSE in the WHERE clause.
So, entity_id = 12 will be returned by the query but entity_id = 129 will be filtered out.
& is bitwise and operator
please be aware that this condition is terribly wrong when you're looking for exact 30 for id, for example it will match 62 and 2, 4, 6, ... also (any integer that has common 1 in the 5 least-significant digits with 11110 (30 in binary) in it's binary form)

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?

Transforming a column to have 10 Digits

I have a csv file that contains phone numbers, some of them have 9 digits and some of them have 10. Is there a command that would allow the transformation of the column such that numbers that have only 9 digits will have a 0 appended in front of the numbers.
For example,
if the column has values "443332332" and "0441223332", I would like to have the value of the one with 9 digits changed to "0443332332"?
Sorry, I should have elaborated.
I was wondering if there was a command to do it in SQLlite easily? I prefer not to use excel to transform the column as if I can get it to working with sqllite it would be so much easier and faster.
A more generic solution would be:
select substr('0000000000'||'1234567', -10, 10) from table_name;
The above query would always return 10 digits and add leading zeroes to the missed out number of digits.
For example, the above query would return : 0001234567
For Update, use
UPDATE TABLE_NAME SET PHONE_NO = substr('0000000000'|| PHONE_NO, -10, 10);
If you're sure that just prepending a zero on strings with length 9 will work for your application, something simple will work:
SELECT CASE WHEN LENGTH(phone_number) = 9 THEN '0'||phone_number
ELSE phone_number
END AS phone_number
FROM your_table
;
You could also update the table, depending on your needs:
UPDATE your_table
SET phone_number = '0'||phone_number
WHERE LENGTH(phone_number) = 9
;
Open the .csv using Excel,
Add a filter to the column,
Sort from A-Z to get all the columns with 9 digits,
Then follow the steps here
http://office.microsoft.com/en-au/excel-help/keep-leading-zeros-in-number-codes-HA010342581.aspx

MySQL: compare a mixed field containing letters and numbers

I have a field in the mysql database that contains data like the following:
Q16
Q32
L16
Q4
L32
L64
Q64
Q8
L1
L4
Q1
And so forth. What I'm trying to do is pull out, let's say, all the values that start with Q which is easy:
field_name LIKE 'Q%'
But then I want to filter let's say all the values that have a number higher than 32. As a result I'm supposed to get only 'Q64', however, I also get Q4, Q8 and so for as I'm comparing them as strings so only 3 and the respective digit are compared and the numbers are in general taken as single digits, not as integers.
As this makes perfect sense, I'm struggling to find a solution on how to perform this operation without pulling all the data out of the database, stripping out the Qs and parsing it all to integers.
I did play around with the CAST operator, however, it only works if the value is stored as string AND it contains only digits. The parsing fails if there's another character in there..
Extract the number from the string and cast it to a number with *1 or cast
select * from your_table
where substring(field_name, 1, 1) = 'Q'
and substring(field_name, 2) * 1 > 32

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).