I have a table
| John
| Robert
| Mary
| James
| Bond
i want to remove characters with prefix 'J' with substr
| ohn
| Robert
| Mary
| ames
| Bond
this my sql code, but still not working
SELECT SUBSTR(name,2) FROM table_name WHERE name LIKE 'J%'
The query you wrote says "show me all the names that needed to be modified", but what I think you want is, "Show me ALL the names, but names that follow a particular pattern I want you to modify first."
The job of modifying the data in the results is the responsibility of the SELECT statement. You've touched on it yourself with your use of SUBSTR. So you want to pull all the names, but only change some of them. Further study into the catalog of MySQL string operations reveals a dizzying array of options. The goal is "SELECT name but if name starts with 'J' then chop that off."
For educational purposes, I encourage you to try to implement this with IF logic, but ultimately that's not necessary.
And while the ultimately powerful regex functions are tempting, there's a simpler option, TRIM. TRIM allows you to say, "chop this string from the front and/or back of this other string."
Since you want all results, there is no WHERE clause anymore, and your query is simply
SELECT TRIM(LEADING 'J' FROM name) FROM table_name
Look at that. FROM meaning two different things. No one ever said SQL was pretty.
If your actual use-case is trickier than simple TRIM can handle, there's a whole bunch more functions to peruse, and ultimately there's regex.
You can able to check others forms to use TRIM function in a following link:
TRIM Functions
Related
I am retrieving a long text blurb for a row. Example: a description for a book. Is there a way that I can reference other values of the same row in the longer text as a form of variable. The idea here being that I don't have to comb through the entire long text output and change every instance of the value where referenced.
Using the same as before: a description which is a column retrieved from the same row as say the title and author of the same book:
"$TITLE is a book written by $AUTHOR etc. etc."
If for example the same row had a title column and author column with the value of "Huckleberry Fin" and "Mark Twain" and a description column with the value of "$TITLE is a book written by $AUTHOR etc. etc."" .. When the description was retrieved, the description would read "Huckleberry Fin is a book written by Mark Twain etc. etc."
Re-Using the same example:
If the above row's title were updated to "The Adventures of Huckleberry Finn" without updating the description, which would be a laborious and tedious process that I would like to avoid, when the description is retrieved it would read: "The Adventures of Huckleberry Finn is a book written by Mark Twain"
Maybe this doesn't exist and I would have to make my own engine for it web server side, but it seems like the best option for efficiency would be to have this done in the database and not the web server. Maybe I don't know enough about MySQL to know that this could be achieved using something like a view for instance. Anyway, it seems like this would be a very common thing to have done on the server and I can't imagine that this cannot be done... but then again, maybe I am missing something really simple.
You could use REPLACE:
SELECT title, REPLACE(description, '$TITLE', title) as description FROM books
But it's going to be ureadable if you need to replace multiple placeholders using nested REPLACE expressions:
SELECT title,
REPLACE(
REPLACE(description, '$TITLE', title),
'$MAINCHARACTER',
main_character
) as description
FROM books
I would rather do it in application language. For example with PHP you could use:
$description = str_replace(
['$TITLE', '$MAINCHARACTER'],
[$title, $mainCharacter],
$description
);
Adding more placeholders wouldn't make it unreadable.
[..] but it seems like the best option for efficiency would be to have
this done in the database and not the web server.
I don't see any reason, why any language should do that less efficient than MySQL.
Anyway, it seems like this would be a very common thing to have done
on the server
I doubt that. You will find a lot of comments like "Why don't you do that in application language?". At least MySQL has a very limited support for string manipulation.
Are you trying to call different data within the same row? You can use mysql_fetch_row.
If yes, you can add a column of index, like
=============================
index |title |character
1 | Huckleberry Fin | Tom Sawer
2 | ABC | John
==============================
And say you have your table name called "books", Then you do
$handle = mysql_query('SELECT * FROM books WHERE index=1');
$row = mysql_fetch_row($handle);
so $row[0]=1, $row[1]=Huckleberry Fin, and $row[2]=Tom Sawer
You can take a look at this manual.
And you may want to learn how to use escape functions like mysql_escape_string()here.
P.S. Sorry for the ugly table drawn LOL
I'm working on a query which I thought should be quite intuitive, but somehow I'm facing a bit of issues when implementing it. I guess what I'm trying to achieve is to match a string stored in MySQL DB without space and punctuation (other creative approaches are more than welcome). At the same time I would like the query to handle Unicode characters in diacritics insensitive fashion (so options like REGEXP are kinda out of luck). And the last condition is I'm on MySQL 5.5 with InnoDB engine, so full-text indexing is not supported (but I'm open to upgrade to 5.6/5.7 if it helps sorting this out).
Consider the scenario which the string Hello-World from John Doe is stored in DB. I would like to find it when given the search string HelloWorld or JohnDoe. To be more general, the string in DB can contain brackets, understores and any other punctuation (not limited to ASCII but can compromise for now), while the search string can be a combination of words with or without any separators in between. The closest I've gotten so far is to daisy chain the REPLACE function for a list of known punctuation, like below:
SELECT text FROM table WHERE REPLACE(REPLACE(text, '-', ''), ' ', '') LIKE '%JohnDoe%'
My questions are:
Is there a better way instead of using the daisy chain above?
If that's the only solution, how will the performance be impacted when I chain up hundred or more REPLACE functions?
Thanks in advance for your help.
I don't know how restrictive your searches must be, but you could try to strip out all non-alphanumeric characters from it, so that you end up with a string like "HelloWorldfromJohnDoe" that you match with instead.
Have a look at this answer: How to remove all non-alpha numeric characters from a string?
You might have to change it around a bit though to make it fir your purposes. I changed it from CHAR(32) to CHAR(255) to make sure I could get the column, but you might want to look into changing the function altogether to fit your data more precisely.
Then you something like this:
SELECT *
FROM testing
WHERE alphanum(test) LIKE CONCAT('%', alphanum('John Doe'), '%')
which should give you a hit.
Method 1
I would have another column on the schema containing an "hashed" version of the name, for example, let's say you have the user:
John Doe The Great
This name hashes to
johndoethegreat
The hash function is coded in such a way that all of the following strings:
John_Doe_THE_great
John Doe The GREAT
John.Doe.The.Great
johnDOE___theGreat
john Doe the great
___john____DOE____THE____great
hash to the same value
johndoethegreat
It's trivial to write such a function. This way you can get the user input, hash it and then compare it against the hash column in your database
Names like:
Jon Doe
John Doo
will not be found of course
Method 2
Use the FULLTEXT search feature built-in in MySQL, sort the results by score and pick the first non zero entry
http://blog.oneiroi.co.uk/mysql/php/mysql-full-text-search-with-percentage-scoring/
I am totally missing the point of your question. You appear to have the string:
Hello-World from John Doe
If you want to find this when the search string is JohnDoe or John Doe, then you only need to substitute spaces:
where replace(text, ' ') like concat('%', 'JohnDoe', '%')
If you want a string that contains both "John" and "Doe" in that order, then:
where replace(text, ' ') like concat('%', 'John%Doe', '%')
I fail to see why 100 nested replace()s would be needed.
I am trying to do a regex match to MySQL query (actually, it MariaDB) a table to find any word in a filepath that contains the string "!Mutex" or were the folder ends with a capital "M".
So if the cell contained the following paths.
-------------
|Path_Folder|
-------------------------------------------------------
|E:\folder01\folder01\folder03\!Mutex\folder05 |
|E:\folder01\folder01\folder03\folder4\!Mutex\folder06|
|E:\folder01\folder01\folder03\folder04\folderM |
-------------------------------------------------------
I'm NOT trying to port this anywhere (no php), just trying to find the results.
I know you asked for a regex solution, but sometimes that's not the answer. :-)
You can do this instead with a normal SQL LIKE expression.
SELECT
Path_Folder
FROM
Your_Table
WHERE
(Path_Folder LIKE '%!Mutex%')
OR
(Path_Folder LIKE '%M')
A LIKE should work just fine for what you need, and be faster (and easier to read/maintain) than a regex.
I have a mysql table with a list of keywords such as:
id | keywords
---+--------------------------------
1 | apple, oranges, pears
2 | peaches, pineapples, tangerines
I'm trying to figure out how to query this table using an input string of:
John liked to eat apples
Is there a mysql query type that can query a field with a sentence and return results (in my example, record #1)?
One way to do it could be to convert apple, oranges, pears to apple|oranges|pears and use RLIKE (ie regular expression) to match against it.
For example, 'John liked to eat apples' matches the regex 'apple|orange|pears'.
First, to convert 'apple, oranges, pears' to the regex form, replace all ', ' by '|' using REPLACE. Then use RLIKE to select the keyword entries that match:
SELECT *
FROM keywords_table
WHERE 'John liked to eat apples' RLIKE REPLACE(keywords,', ','|');
However this does depend on your comma-separation being consistent (i.e. if there is one row that looks like apples,oranges this won't work as the REPLACE replaces a comma followed by a space (as per your example rows).
I also don't think it'll scale up very well.
And, if you have a sentence like 'John liked to eat pineapples', it would match both of the rows above (as it does have 'apple' in it). You could then try to add word boundaries to the regex (i.e. WHERE $sentence RLIKE '[[:<:]](apple|oranges|pears)[[:>:]]'), but this would screw up matching when you have plurals ('apples' wouldn't match '[wordboundary]apple[wordboundary]').
Hopefully this isn't more abstract than what you need but maybe good way of doing it.
I haven't tested this but I think it would work. If you can use PHP you can use str_replace to turn the spaces into keyword LIKE '%apple%'
$sentence = "John liked to eat apples";
$sqlversion = str_replace(" ","%' OR Keyword like '%",$sentence );
$finalsql = "%".$sqlversion."%";
the above will echo:
%John%' OR Keyword like '%liked%' OR Keyword like '%to%' OR Keyword like '%eat%' OR Keyword like '%apples%
Then just combine with your SQl statement
SQL ="SELECT *
FROM keywords_table
WHERE Keyword like" . $finalsql;
Storing comma delimited data is... less than ideal.
If you broke up the string "John liked to eat apples" into individual words, you could use the FIND_IN_SET operator:
WHERE FIND_IN_SET('apple', t.keywords) > 0
The performance wouldn't be great - this operation is better suited to Full Text Search.
I'm not aware of any direct solution to that type of query. But Full Text Search is a possibility. If you have a full-text index on the field of interest then a search with OR between each word in the sentence (although I think the OR operator is implied) would find that record ... but it might also find more than you want too.
I really don't think what you are looking for is completely possible but you can look into Full Text Search or SOUNDEX. SOUNDEX, for example, can do something like:
WHERE SOUNDEX(sentence) = SOUNDEX('%'+keywords+'%');
I have never tried it in this context but you should and let me know how it works out.
I'm looking for both MySQL and PostgreSQL solutions for this kind of problem.
Say I have a number of records with a title field. The titles are book or movie titles, like "The Cat in the Hat" and "Robin Hood". But while the titles must be displayed in their original form, they ought to be sorted in the way that libraries sort them, which is by moving any article, like "The" or "An" to the end of the title.
So "The Cat in the Hat" is sorted as if it were "Cat in the Hat, The".
What's the best way either to design the schema or write the query so that these records are sorted by title in the same way that libraries sort the title? (I also wish I knew the technical term for this type of ordering by title.) Also, what performance considerations should I be aware of and what indexes should I create?
Why don't you just add a "title_prefix" field to the table and move all these "the" and "a" strings there? When you're ordering you would use the "title" field, and when you are presenting the title you could do the concatenation in any way you wish.
Create a custom function that (sortableTitle, perhaps?) that will modify strings starting with your unwanted words. Finish your query statement with order by sortableTitle(title). This will incur an extra CPU cost, though you'll have to benchmark to know how much so.
You could create an extra column (sortTitle) that is populated by a trigger. This will take up some space, but then your server will be able to sort rows by an index.
Excepting the above, you cannot (without modifying the database server code) directly create an index that is in the order you want. As far as I can tell, that applies to both MySQL and PostgreSQL.
iTunes achieves this by having a second field in which the title is stored in the desired sorting format and sorting on this instead of title. It does sound like the cheap way out, but when you consider the performance implications of doing string manipulations on every title every time you do a select statement that orders by title, against doing string manipulations each time you insert or update the title, it does make sense.
Select * from TitleTable
Order by
Case when substring(title,0,4) = 'The ' then substring(title, 4, len(title)-4)
when substring(title,0,3) = 'An ' then substring(title, 3, len(title)-3)
when substring(title,0,2) = 'A ' then substring(title, 2, len(title)-2)
else title
end
I would suggest you split the title field in two fields: mainTitle and pre.
When a title is added, check if it starts with "A", "The" or other prefixes and split it (perhaps with a trigger) into the two fields. Your table would look like this:
| pre | mainTitle |
|-----|----------------|
| The | Cat in the Hat |
| A | Space Odyssey |
| | Eyes Wide Shut |
So, you can have an index on the mainTitle field and use it for sorting.
When you want to show the full title, concat the two fields, in either of the two forms.
If you choose this way, you'll have to modify accordingly the code for when a user gives a title to search in your table. The given title will have to be split the same way before searching the mainTitle field.
You'll have to be very, very careful with the code (trigger or other) that does the spliting so some special cases are caught correctly. You wouldn't want to have the A = B or the A B C: learn the alphabet books shown and sorted as = B, A and B C: learn the alphabet, A