I have a table with a varchar field that contains a description with variable lenght. I want to read the 4th last letters from the right.
For example if the table contained:
|col1 |
+-----+
|20161512_NL_Luxus_1_DE |
|20161512_NL_Premium_2_DE |
|20161512_NL_SDT_4_DE|
I want a query that will return:
|result|
+------+
|1 |
|2 |
|4 |
Thanks in advance!
SUBSTRING_INDEX seems like it would be a good fit for what you're trying to accomplish:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(col1, '_', -2), '_', 1);
See the MySQL Docs for more info on usage.
Essentially, the inner call to SUBSTRING_INDEX is finding the second to last _ character and returns everything to the right of it. The outer SUBSTRING_INDEX call is then finding the first _ from this result and returning everything up until that point.
Related
I'm trying to delete lines in specific column from all rows that contains specific words.
For example:
Remove lines that contain word apple and it is always at the beginning of the line.
+--+------------------+
|ID|data |
+--+------------------+
|1 |sometext1 |
| |sometext2 |
| |apple sometext3 |
| |sometext4 |
+--+------------------+
|2 |apple sometext5 |
| |sometext6 |
+--+------------------+
so the result would be:
+--+------------------+
|ID|data |
+--+------------------+
|1 |sometext1 |
| |sometext2 |
| |sometext4 |
+--+------------------+
|2 |sometext6 |
+--+------------------+
'SometextX' is different in every line, number of lines is different in every row and it has different number of characters in every line.
I really need this in MySQL any help would be appreciated.
You would be better off using REGEXP here to match patterns in each line:
DELETE FROM yourTable WHERE text REGEXP '^apple';
REGEXP allows for fairly complex regex matching, and would be useful if your requirement changes or gets more complex later on.
Edit: MySQL has no built in support for regex replacement, so there is no easy way to accomplish what you want.
A general regex pattern to remove the word apple would be \bapple\b. You may search on this pattern and replace with empty string.
You would use where:
where textcol not like 'apple%' or textcol is null
This can be part of a select or a delete (the question mentions "result" which suggests the former and "delete" which suggests the latter). It is not clear whether you actually want to change the data or whether you just want the result set without these words.
Note: you can do this without or and still handle NULL values, because MySQL has a NULL-safe equality operator:
where not left(textcol, 5) <=> 'apple'
You can use MySQL functions to select the right rows and to update with new data as follows:
UPDATE `yourTable` SET `yourField` = REPLACE(yourField, 'apple', '') WHERE yourField LIKE '%apple%'
If you don't want to delete the whole row, you can run these 3 queries in this order
update your_table set text=replace(text,substring(text,#start:=locate('\napple',text),locate('\n',text,#start+1)-#start+1),'');
update your_table set text=if((#start:=locate('apple',text))=1,replace(text,substring(text,#start,locate('\n',text,#start+1)-#start+1),''),text);
update your_table set text=if((#start:=locate('apple',text))=1,replace(text,substring(text,locate('apple',text)),''),text);
update #1 will remove apple in the middle of the text (prefixed by \n)
update #2 will remove apple at the beginning of its row (nothing before) and having following rows
update #3 will remove remaining cases
I have my table like this:
|name |
-----------------
|Joseph Jackson |
|Aiden Chase |
|Luke Benjamin |
|Joseph |
|Joseph2 |
If I search for the word Joseph (SELECT * from myTable where name="Joseph" ) I woud get only the last result:
|name |
-----------------
|Joseph |
If I search for the word Jackson, I won't get any results.
That is what I DON'T want.
What I want is to get the records that exist in the exact word searched, for example:
if the word searched is Joseph, I woud get:
|name |
-----------------
|Joseph |
|Joseph Jackson |
*Notice that Joseph2 is not in the result set.
If the word searched is Jackson, I woud get:
|name |
-----------------
|Joseph Jackson |
*But I cannot use like '%Jose%' (the use of like) cuz I will get Joseph2 and I want the exact word(Jose).
*If the word searched is Jose for example I shouldn't get any result, cuz Jose is not in the data (also I shouldn't get records that contain the Joseph word).
The only way I've found is using regex for example:
SELECT * from myTable where REGEXP [[:<:]]Joseph[[:>:]]
|name |
-----------------
|Joseph |
|Joseph Jackson |
SELECT * from myTable where REGEXP [[:<:]]Jackson[[:>:]]
|name |
-----------------
|Joseph Jackson |
I want this results but without using regex and whithout rlike, is there any way? How? thanks.
This screams for FULLTEXT search
ALTER TABLE T ADD FULLTEXT INDEX (name);
SELECT * FROM T WHERE MATCH (name) AGAINST ('+Joseph' IN BOOLEAN MODE);
FIDDLE
Although full text as #Mihai suggests is definitely the way to go for production, if you want to do a one-off search without building extra indices you can just use LIKE by adding spaces around the names and search for the name including surrounding spaces;
SELECT * FROM myTable
WHERE CONCAT(' ', name, ' ') LIKE CONCAT('% ', 'joseph', ' %')
Note that this will definitely not use any indexes, so can be useful for admin purposes but not for a production application that cannot handle full table scans.
allow your stored procedure to accept a parameter for #name then you can use the WHERE clause
WHERE name = #name
I am using MySQL, and I have a function which will accept a col data from a table row, and return a table-valued function. for example, a function like this:
CREATE FUNCTION [dbo].[wordlongerthan4](
#input text
) returns #result table(
pos int,
word varchar,
)
which will return the word longer than 4char and its position.
i want to do a sql something like below
select t.name,wordlongerthan4(t.content) from sometable as t;
on table
------------------------------------------------------------------
| id | name | content |
------------------------------------------------------------------
|1 | my1 | i love something and nothing |
|2 | my2 | It is a sunny day today |
to get the result:
|name | pos | word |
--------------------------------
|my1 |8 |something |
|my1 |22 |nothing |
|my2 |9 |sunny |
|my2 |20 |today |
How could i write the sql?(the function wordlongerthan4 is already there,i only need the sql!)
What you are talking about doing is:
Looping through each record and extracting the content.
Splitting the content by a delimiter (space, in this case).
Measuring the length of each part
Adding the part to an array of successful results it its length < n
(4).
Returning the part, along with the original id and name from the
record it originally came from.
Like ajreal said, this is something that would best be done at the application layer, presumably inside of your php/java/whatever.
There is currently no built-in string explode/split function, but this question here might prove useful: Equivalent of explode() to work with strings in mysql.
You can (ab)use the new JSON_TABLE function in MySQL 8 to do this:
set #input = 'i love something and nothing';
SELECT Value, LENGTH(Value) as Length, LOCATE(Value, #delimited) as pos
FROM
JSON_TABLE(
CONCAT('["', REPLACE(#delimited, ' ', '", "'), '"]'),
"$[*]"
COLUMNS(
Value varchar(50) PATH "$"
)
) data
where LENGTH(Value) > 4;
I'm trying create a MySQL query which will return a row (or more, but I'm only interested in a single row) an area suggestion when provided with a postcode.
So, I have a table like so
area_id | postcode_start
1 | NE
2 | DL
3 | DL1
4 | DL2
5 | DL6
...
And I wish to provide a postcode, for example DL5 8TB and for it to return the row 1 | DL as the first characters match.
Another example DL6 4GH would return two rows, 5 | DL6 and 2 | DL
SELECT *
FROM (`area_postcodes`)
WHERE CONCAT(LOWER(`area_postcodes`.`postcode_start`),'%')
LIKE 'dl5 8tb';
Apparently it's a valid query but it always returns an empty set.
You'll see I've added the wildcard % to the other side of the query but it doesn't seem to work and I don't know where else to even consider guessing how to go about it, it's almost like the reverse of a normal MySQL LIKE query.
You were very close:
SELECT
*
FROM
area_postcodes
WHERE
'dl5 8tb' LIKE CONCAT(postcode_start, '%');
I have a series of varchar fields in a MySQL database that are "numbered":
+-----------+
| name |
+-----------+
| thing 1 |
| thing 2 |
| thing 3 |
| ... |
| thing 10 |
| thing 11 |
+-----------+
I want to order them as listed above. However, a simple ORDER_BY table.name produces something like the following:
thing 1
thing 10
thing 11
thing 2
thing 3
...
This makes some sense, since MySQL is treating the entire field as a String (varchar). However, I've tried numerous methods to sort including CAST(name AS DECIMAL) and name + 0. This will only sort by the decimal part, ignoring the string part. None of these work because I need to sort by name first and then sort by the trailing decimal.
I tried ORDER_BY name, name + 0, but nothing seems to work. How do I perform and ORDER_BY and then ORDER_BY within that subset? (I think that will work).
You need to have two sorts - first by the name part, and second by the numeric part, like this:
order by left(name,instr(name,' ')),cast(right(name,instr(name,' ')+1) as decimal)
The function SUBSTRING_INDEX can split the string.
SELECT SUBSTRING_INDEX(name, ' ', 1) AS a, CAST(SUBSTRING(name, ' ', -1) AS DECIMAL) AS b
FROM t
ORDER BY a, b