I am using the following to only select the first 40 characters from a column
SELECT SUBSTRING(w.item_title,1,40) as title from tableName blah blah
What I really want to do though is:
If w.item_title is over 40 characters, return only the first 40 and append with ... else just return w.item_title as it is
Is this possible at SELECT stage and should it be done there? Or should it be processed after the fact?
I am using JS to display the results.
SELECT SUBSTR(INSERT(w.item_title, 41, 3, '...'), 1, 43)
FROM ...
See the manual on the INSERT() String function for examples.
INSERT(str,pos,len,newstr)
Returns the string str, with the substring beginning at position pos
and len characters long replaced by the string newstr. Returns the
original string if pos is not within the length of the string.
Replaces the rest of the string from position pos if len is not within
the length of the rest of the string. Returns NULL if any argument is
NULL.
EDIT
Last parameter of SUBSTR should be 43 as pointed out by Joachim.
QUERY:
SELECT CASE WHEN LENGTH(w.item_title)>40
THEN SUBSTRING(w.item_title,1,40)
ELSE w.item_title END as title
from tableName w
You can just use an 'IF' to append your suffix;
SELECT CONCAT(SUBSTRING(w.item_title,1,40),
IF(LENGTH(w.item_title)>40, '...', '')) as title
FROM tableName w
SQLfiddle demo here.
On whether it should be done in the database, that's a trickier question that can as always be answered with "it depends".
If your text is long (for example articles), it's rather clear cut that you don't want to transfer the whole article if you only need the first 40 characters, but if the texts are short, you may want to offload the calculation from the database. It's easy to add web servers, but scaling the database up is expensive.
You can also try with Left
SELECT CONCAT(Left(w.item_title,40),
IF(LENGTH(w.item_title)>40, 'something', '')) as title
FROM tableName w
;
Another:
SELECT case when Length(w.item_title) > 40 then
Left(w.item_title,40) else
CONCAT(coalesce(w.item_title,''), 'something') End as title
FROM tableName w
;
Related
I am trying to pull a product code from a long set of string formatted like a URL address. The pattern is always 3 letters followed by 3 or 4 numbers (ex. ???### or ???####). I have tried using REGEXP and LIKE syntax, but my results are off for both/I am not sure which operators to use.
The first select statement is close to trimming the URL to show just the code, but oftentimes will show a random string of numbers it may find in the URL string.
The second select statement is more rudimentary, but I am unsure which operators to use.
Which would be the quickest solution?
SELECT columnName, SUBSTR(columnName, LOCATE(columnName REGEXP "[^=\-][a-zA-Z]{3}[\d]{3,4}", columnName), LENGTH(columnName) - LOCATE(columnName REGEXP "[^=\-][a-zA-Z]{3}[\d]{3,4}", REVERSE(columnName))) AS extractedData FROM tableName
SELECT columnName FROM tableName WHERE columnName LIKE '%___###%' OR columnName LIKE '%___####%'
-- Will take a substring of this result as well
Example Data:
randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz123&hello_world=us&etc_etc
In this case, the desired string is "xyz123" and the location of said pattern is variable based on each entry.
EDIT
SELECT column, LOCATE(column REGEXP "([a-zA-Z]{3}[0-9]{3,4}$)", column), SUBSTR(column, LOCATE(column REGEXP "([a-zA-Z]{3}[0-9]{3,4}$)", column), LENGTH(column) - LOCATE(column REGEXP "^.*[a-zA-Z]{3}[0-9]{3,4}", REVERSE(column))) AS extractData From mainTable
This expression is still not grabbing the right data, but I feel like it may get me closer.
I suggest using
REGEXP_SUBSTR(column, '(?<=[&?]random_code=[^&#]{0,256}-)[a-zA-Z]{3}[0-9]{3,4}(?![^&#])')
Details:
(?<=[&?]random_code=[^&#]{0,256}-) - immediately on the left, there must be & or &, random_code=, and then zero to 256 chars other than & and # followed with a - char
[a-zA-Z]{3} - three ASCII letters
[0-9]{3,4} - three to four ASCII digits
(?![^&#]) - that are followed either with &, # or end of string.
See the online demo:
WITH cte AS ( SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz123&hello_world=us&etc_etc' val
UNION ALL
SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz4567&hello_world=us&etc_etc'
UNION ALL
SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz89&hello_world=us&etc_etc'
UNION ALL
SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz00000&hello_world=us&etc_etc'
UNION ALL
SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-aaaaa11111&hello_world=us&etc_etc')
SELECT REGEXP_SUBSTR(val,'(?<=[&?]random_code=[^&#]{0,256}-)[a-zA-Z]{3}[0-9]{3,4}(?![^&#])') output
FROM cte
Output:
I'd make use of capture groups:
(?<=[=\-\\])([a-zA-Z]{3}[\d]{3,4})(?=[&])
I assume with [^=\-] you wanted to capture string with "-","\" or "=" in front but not include those chars in the result. To do that use "positive lookbehind" (?<=.
I also added a lookahead (?= for "&".
If you'd like to fidget more with regex I recommend RegExr
I have some long text saved in one of the columns of my table.
And there is a part of the text I want to get from it...
For example, everything between 'words' IMPORTANTSTART and IMPORTANTEND...
How can I get it, if I don't know the exact length of that part?
I can't use SUBSTRING() as the number of characters is always different.
Is there any way to do that? I've tried to find some similar function that would allow me to do that, but couldn't find anything...
A lot of words here IMPORTANTSTART some data IMPORTANTEND more words
Even more words IMPORTANTSTART very important data IMPORTANTEND words
Maybe there is a way to remove everything before IMPORTANTSTART and after IMPORTANTEND from the query output, while not changing this text in the database?
Try with SUBSTRING_INDEX:
SET #s := 'A lot of words here IMPORTANTSTART some data IMPORTANTEND more words';
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(#s, 'IMPORTANTSTART', -1), 'IMPORTANTEND', 1)
Output:
some data
I think this can work. As an example, I use the strings abc and cba as start and end delimiters, respectively.
select #string := 'text abc important cba more text'
, #start_delim := 'abc'
, #end_delim := 'cba'
, #start_pos := instr(#string, #start_delim) + length(#start_delim)
, #end_pos := instr(#string, #end_delim)
, mid(#string, #start_pos, length(#string) - #end_pos - 1)
Edit
All you need to do is add your table to use this for all your data. Also, you can use a subquery to initialize the relevant variables, and "compact" expressions so you only get what you need:
select articles
, mid(
articles,
instr(articles, #start_delim) + length(#start_delim),
length(articles) - instr(articles, #end_delim) - 1
) as result
from (select #start_delim := 'abc', #end_delim := 'cba') as init
, myarchive
As you can see, all that was needed was replace #string with the column name you want to work with.
You can use INSTR to calculate indexes of your start/end for SUBSTRING.
I want to truncate the first letter of a string which have size more than 11 character.
I know I can use substring function like
SELECT SUBSTRING(name, 1, 10) from table1;
which will truncate and return me the first 10 letter. what should I do if I want to remove the character from the beginning if the string is greater than 10 character.
abcdefghijklmn ==> efghijklmn
How about RIGHT():
SELECT RIGHT(name, 10)
FROM table1;
Demo: SQL Fiddle
RIGHT() returns a specified number of characters from the right side of a string.
If you want to apply any function only in certain situations, a CASE statement can be used.
create table table1(name char(25));
insert into table1 values('abcdefghijklmn');
select right(name,10) from table1;
RIGHT() is the function you need to use.
I need to extract everything after the last '=' (http://www.domain.com?query=blablabla - > blablabla) but this query returns the entire strings. Where did I go wrong in here:
SELECT RIGHT(supplier_reference, CHAR_LENGTH(supplier_reference) - SUBSTRING('=', supplier_reference))
FROM ps_product
select SUBSTRING_INDEX(supplier_reference,'=',-1) from ps_product;
Please use this for further reference.
Try this (it should work if there are multiple '=' characters in the string):
SELECT RIGHT(supplier_reference, (CHARINDEX('=',REVERSE(supplier_reference),0))-1) FROM ps_product
Try this in MySQL.
right(field,((CHAR_LENGTH(field))-(InStr(field,','))))
In MySQL, this works if there are multiple '=' characters in the string
SUBSTRING(supplier_reference FROM (LOCATE('=',supplier_reference)+1))
It returns the substring after(+1) having found the the first =
If your string is
str = 'abc=def=ghi'
To select to the right:
select substring_index(str,'=',-1) from tablename ==> result is 'ghi'
select substring_index(str,'=',-2) from tablename ==> result is 'def=ghi'
To select to the left
select substring_index(str,'=',-1) from tablename ==> result is 'abc'
select substring_index(str,'=',2) from tablename ==> result is 'abc=def'
I've been working on something similar and after a few tries and fails came up with this:
Example:
STRING-TO-TEST-ON = 'ab,cd,ef,gh'
I wanted to extract everything after the last occurrence of "," (comma) from the string... resulting in "gh".
My query is:
SELECT SUBSTR('ab,cd,ef,gh' FROM (LENGTH('ab,cd,ef,gh') - (LOCATE(",",REVERSE('ab,cd,ef,gh'))-1)+1)) AS `wantedString`
Now let me try and explain what I did ...
I had to find the position of the last "," from the string and to calculate the wantedString length, using LOCATE(",",REVERSE('ab,cd,ef,gh'))-1 by reversing the initial string I actually had to find the first occurrence of the "," in the string ... which wasn't hard to do ... and then -1 to actually find the string length without the ",".
calculate the position of my wantedString by subtracting the string length I've calculated at 1st step from the initial string length:
LENGTH('ab,cd,ef,gh') - (LOCATE(",",REVERSE('ab,cd,ef,gh'))-1)+1
I have (+1) because I actually need the string position after the last "," .. and not containing the ",". Hope it makes sense.
all it remain to do is running a SUBSTR on my initial string FROM the calculated position.
I haven't tested the query on large strings so I do not know how slow it is. So if someone actually tests it on a large string I would very happy to know the results.
For SQL Management studio I used a variation of BWS' answer. This gets the data to the right of '=', or NULL if the symbol doesn't exist:
CASE WHEN (RIGHT(supplier_reference, CASE WHEN (CHARINDEX('=',supplier_reference,0)) = 0 THEN
0 ELSE CHARINDEX('=', supplier_reference) -1 END)) <> '' THEN (RIGHT(supplier_reference, CASE WHEN (CHARINDEX('=',supplier_reference,0)) = 0 THEN
0 ELSE CHARINDEX('=', supplier_reference) -1 END)) ELSE NULL END
SELECT NULLIF(SUBSTRING_INDEX(column, '=', -1), column)
From select statement, in a filed I want to remove last characters is character if its number. Is there string function available in MySQL?
for these two SQL I want
test
as output
select 'test1';
select 'test';
Another way is to use REGEXP,
SET #val = 'test12';
SELECT CONCAT(LEFT(#val, CHAR_LENGTH(#val) - 1),
IF(RIGHT(#val, 1) REGEXP '[0-9]' = 0, RIGHT(#val, 1), ''))
SQLFiddle Demo
SQLFiddle Demo (another example)
To remove the last character if it's numeric, one way to do this without using a regular expression is with LEFT, RIGHT and LENGTH :
select if( right(yourfield,1) = 0 && right(yourfield,1) != '0',
yourfield,
left(yourfield, length(yourfield) - 1))
from yourtable;
To replace all trailing numeric values, you can use REVERSE:
select if( cast(reverse(yourfield) as signed) = 0 && right(yourfield,1) != '0',
yourfield,
left(yourfield, length(yourfield) - length((reverse(yourfield) + 0))))
from yourtable;
SQL Fiddle Demo
When casting fields as integers/signed in MySQL, it will cast all the numeric characters up to the first non-numeric character -- thus making the REVERSE work. If the last character is not numeric, it results in 0.
Using the IF check above, if the last character isn't numeric, then it prints the original value, else it prints all but the last character.
here is a pointer:
use a union between two queries.
in the first - either use REGEX, or grab the substr of the field where another substr for the last char is a number,
then union the text field where the substr of the last char is not a number.
You might want to use Regular Expressions inside MySQL. This package might help you https://launchpad.net/mysql-udf-regexp. However, I do not recommend to do it inside MySQL statement as it might be slow. You would better to do it after grabbing the value inside your programming language.