How to remove digits from the end of the string using SQL - mysql

Please, could you answer my question.
How to remove digits from the end of the string using SQL?
For example, the string '2Ga4la2009' must be converted to 2Ga4la. The problem is that we can't trim them because we don't know how many digits are in the end of the string.
Best regards, Galina.

This seems to work:
select left( concat('2Ga4la2009','1'), length(concat('2Ga4la2009','1')) - length(convert(convert(reverse(concat('2Ga4la2009','1')),unsigned),char)))
The concat('myvalue', '1') is to protect against numbers that end in 0s.
The reverse flips it around so the number is at the front.
The inner convert changes the reversed string to a number, dropping the trailing chars.
The outer convert turns the numeric part back to characters, so you can get the length.
Now you know the length of the numeric portion, and you can determine the number of characters of the original value to chop off with the "left()" function.
Ugly, but it works. :-)

Take a look at this: http://www.mysqludf.org/lib_mysqludf_preg/
And if you for some reason can't use UDF, and don't want to do it on the db client side, you can always do the following:
Find the position of the first letter from the end (e.g. the minimum of the 25 LOCATEs on the string's reverse)
Do LEFT(#string, #string_length - #result_of_step_1)
You don't have to do any special handling in case there aren't any digits at the end of the string because in this case LOCATE returns 0.
Cheers

Related

NetSuite Saved Search: REGEXP_SUBSTR Pattern troubles

I am trying to break down a string that looks like this:
|5~13~3.750~159.75~66.563~P20~~~~Bundle A~~|
Here is a second example for reference:
|106~10~0~120~1060.000~~~~~~~|
Here is a third example of a static sized item:
|3~~~~~~~~~~~5:12|
Example 4:
|3~23~5~281~70.250~upper r~~~~~~|
|8~22~6~270~180.000~center~~~~~~|
|16~22~1~265~353.333~center~~~~~~|
Sometimes there are multiple lines in the same string.
I am not super familiar with setting up patterns for regexp_substr and would love some assistance with this!
The string will always have '|' at the beginning and end and 11 '~'s used to separate the numeric/text values which I am hoping to obtain. Also some of the numeric characters have decimals while others do not. If it helps the values are separated like so:
|Quantity~ Feet~ Inch~ Unit inches~ Total feet~ Piece mark~ Punch Pattern~ Notch~ Punch~ Bundling~ Radius~ Pitch|
As you can see, if there isn't something specified it shows as blank, but it may have them in another string, its rare for all of the values to have data.
For this specific case I believe regexp_substr will be my best option but if someone has another suggestion I'd be happy to give it a shot!
This is the formula(Text) I was able to come up with so far:
REGEXP_SUBSTR({custbody_msm_cut_list},'[[:alnum:]. ]+|$',1,1)
This allows me to pull all the matches held in the strings, but if some fields are excluded it makes presenting the correct data difficult.
TRIM(REGEXP_SUBSTR({custbody_msm_cut_list}, '^\|(([^~]*)~){1}',1,1,'i',2))
From the start of the string, match the pipe character |, then match anything except a tilde ~, then match the tilde. Repeat N times {1}. Return the last of these repeats.
You can control how many tildes are processed by the integer in the braces {1}
EG:
TRIM(REGEXP_SUBSTR('|Quantity~ Feet~ Inch~ Unit inches~ Total feet~ Piece mark~ Punch Pattern~ Notch~ Punch~ Bundling~ Radius~ Pitch|', '^\|(([^~]*)~){1}',1,1,'i',2))
returns "Quantity"
TRIM(REGEXP_SUBSTR('|Quantity~ Feet~ Inch~~~ Piece mark~ Punch Pattern~ Notch~ Punch~ Bundling~ Radius~ Pitch|', '^\|(([^~]*)~){7}',1,1,'i',2))
returns "Punch Pattern"
The final value Pitch is a slightly special case as it is not followed by a tilde:
TRIM(REGEXP_SUBSTR('|~~~~~~~~~~ Radius~ Pitch|', '^\|(([^~]*)~){11}([^\|]*)',1,1,'i',3))
Adapted and improved from https://stackoverflow.com/a/70264782/7885772

MySQL failing on LEFT() with String 8863 characters long?

Yet another fun and unexplained issue with MySQL. Code works perfectly fine with all other shorter strings (and has been for months), but when I try to following code on a String that's 8863 in length (designed to simply remove a comma as the last character), it just does nothing. No error or anything. Length is 8863 both before and after the execution (and note the RIGHT check works fine so the LEFT executes, it just fails to remove the last comma). As mentioned, ONLY happens with a very long string.
Anyone know what crazy limitations in MySQL I might be dealing with?
DECLARE var_sql_insert_1 text;
IF (RIGHT(var_sql_insert_1, 1) = ',') THEN
SET var_sql_insert_1 = LEFT(var_sql_insert_1, LENGTH(var_sql_insert_1) - 1);
END IF;
So the issue is I was using LENGTH which was returning the length in BYTES vs. CHAR_LENGTH which returns the length in characters. Sadly, with all the other languages I've used, the default LENGTH value was character and they BYTE_LENGTH was specifically designed to be byte. For MySQL it appears the reverse is true. Doesn't make much sense for a system that's mainly used to store and manipulate TEXT rather than byte data...
Since MySQl 8 where introduced function REGEXP_REPLACE you can use next solution:
SET var_sql_insert_1 = REGEXP_REPLACE(var_sql_insert_1, ',$', '');
The pattern ',$' mean last comma before end of line $
Look the example

Julia: How to find the longest word in a given string?

I am very new in Julia, I got this challenge from the web:
How can I find the longest word in a given string?
I would like to build a function which would allow to obtain the longest string, even in cases where punctuation is used.
I was trying to to the following code:
function LongestWord(sen::String)
sentence =maximum(length(split(sen, "")))
word= [(x, length(x)) for x in split(sen, " ")]
return((word))
end
LongestWord("Hello, how are you? nested, punctuation?")
But I haven't manage to find the solution.
You can use regex too. It only needs a slight change from #Bogumil's answer:
julia> function LongestWord2(sen::AbstractString)
words = matchall(r"\w+", sen)
words[findmax(length.(words))[2]]
end
LongestWord2 (generic function with 1 method)
julia> LongestWord2("Hello, how are you? nested, punctuation?")
"punctuation"
This way you get rid of the punctuations and get the raw word back.
To consolidate the comments here's some further explanation:
matchall() takes a regex, in this case r"\w+" which matches word like substrings, so letters, numbers and lowercases and returns an array of strings that match the regex.
length.() is using the combination of the length function and . which broadcasts the operation across all elements of the array. So we're counting the length of each array element (word).
Findmax() returns a tuple of length 2 where the 2 argument gives us the index of the maximum element. I use this to subset the words array and return the longest word.
I understand that you want to retain punctuation and want to split only on space (" "). If this is the case then you can use findmax. Note that I have changed the order of length(x) and x. In this way you will find the longest word, and among words of equal maximum length you will find the word that is last when using string comparison. Also I put AbstractString in the signature of the function as it will work on any string:
julia> function LongestWord(sen::AbstractString)
word = [(length(x), x) for x in split(sen, " ")]
findmax(word)[1][2]
end
LongestWord (generic function with 1 method)
julia> LongestWord("Hello, how are you? nested, punctuation?")
"punctuation?"
This is the simplest solution but not the fastest (you could loop through the original string by searching consecutive occurrences of space without creating word vector using findnext function).
Other approach (even shorter):
julia> function LongestWord3(sen::AbstractString)
word = split(sen, " ")
word[indmax(length.(word))]
end
LongestWord3 (generic function with 1 method)
julia> LongestWord3("Hello, how are you? nested, punctuation?")
"punctuation?"
My version specifically defines what symbols are allowable (in this case letters, numbers and spaces):
ALLOWED_SYMBOLS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 \t\n"
function get_longest_word(text::String)::String
letters = Vector{Char}()
for symbol in text
if uppercase(symbol) in ALLOWED_SYMBOLS
push!(letters, symbol)
end
end
words = split(join(letters))
return words[indmax(length.(words))]
end
#time get_longest_word("Hello, how are you? nested, punctuation?")
"punctuation"
I doubt it's the most efficient code in the world, but it pulls 'ANTIDISESTABLISHMENTARIANISM' out of a 45,000-word dictionary in about 0.1 seconds. Of course, it won't tell me if there is more than one word of the maximum length! That's a problem for another day...

Convert/encode string to numbers

I'm looking around to encode/cast/convert a string into numbers within a query. Like ASCII() but it only returns the left-most character to its relative code. Is there any function or method available on this topic? -which is actually decode-able
JUST For example:
METHOD("test-string") # Outputs: 25478596325417
This will work for strings up to 8 characters long.
To encode:
SELECT CONV(HEX(string), 16, 10);
To decode:
SELECT UNHEX(CONV(number, 10, 16));
MySQL supports integers up to 64 bit long, and this method uses 8 bits per character. Therefore using this method you can store up to 64 / 8 = 8 characters in an integer.
If hexadecimal is good enough for your application, then then function hex() does what you want. For instance, you can try:
select hex('abc'), hex('abcd')
This will work on arbitrary strings. If this doesn't quite work, then perhaps there is a way to convert the hex representation to something appropriate.
By the way, unhex() will return the original string.
You could use
COMPRESS('ABC)
To get a binary string that is not the string. It can compress an arbitrary size. But it is not clear what you are going to do with the number -- or how you need to store it.
Try this one.
SELECT CAST(HEX(your_string) AS DECIMAL);
I admit, I didn't test it, but it should work.
EDIT:
Some other databases (e.g. Oracle, DB2, PostgreSQL) have the function TRANSLATE() for it. Unfortunately MySQL does not support it. And as far as I know no replacement for this function in MySQL exists currently. So using nested REPLACE() is probably the only option currently.

MySQL integer comparison ignores trailing alpha characters

So lets just say I have a table with just an ID is an int. I have discovered that running:
SELECT *
FROM table
WHERE ID = '32anystring';
Returns the row where id = 32. Clearly 32 != '32anystring'.
This seems very strange. Why does it do this? Can it be turned off? What is the best workaround?
It is common behavior in most programming languages to interpret leading numerals as a number when converting a string to a number.
There are a couple of ways to handle this:
Use prepared statements, and define the placeholder where you are putting the value to be of a numeric type. This will prevent strings from being put in there at all.
Check at a higher layer of the application to validate input and make sure it is numeric.
Use the BINARY keyword in mysql (I'm just guessing that this would work, have never actually tried it as I've always just implemented a proper validation system before running a query) -
SELECT *
FROM table
WHERE BINARY ID = '32anystring';
You need to read this
http://dev.mysql.com/doc/refman/5.1/en/type-conversion.html
When you work on, or compare two different types, one of them will be converted to the other.
MySQL conversion of string->number (you can do '1.23def' * 2 => 2.46) parses as much as possible of the string as long as it is still a valid number. Where the first letter cannot be part of a number, the result becomes 0