MySQL strip ' on where queries - mysql

I have a large table which contains, or not, records that have ' tags like (martin's, lay's, martins, lays, so on).
Actually to search the client can be write exactly text, for example: martin's, to search all records that contains "martin's" but it is complicate, then, I need the client can to search by "martins" or "martin's".
This is a simple example:
A mysql table like:
ID | Title
---------------
1 lays
2 lay's
3 some text
4 other text
5 martin's
I need a sql query to search by lays or lay's and both need show me a Result like:
ID | Title
---------------
1 lays
2 lay's
I'm tried with many post solutions but I cant do that :-(
Appreciate any help.

Just remove the single quote:
select t.*
from t
where replace(t.title, '''', '') = 'lays';

To search if the word contains:
select t.*
from t
where replace(t.title, '''', '') LIKE '%lays%';

Related

MySQL: fix data inserted inside quotes in DB

I need to fix some (bad) inserted data in DB, I had data inserted with single qoutes like: ('love')
I want to move this to (love), without effect on something like (we're),
info table (structure)
id text
1 'love'
2 'man'
3 we're..
4 John
5 'Sarah'
I want to fix "info" table to be:
info table (structure)
id text
1 love
2 man
3 we're..
4 John
5 Sarah
I can select this data using:
select * from info where text like "'%'"
thanks,
try this untested query:
update info set text = replace(text,"'","") where text like "'%'"
You can use this statement to update all the rows of the table.
update Table_Name
set ColumnName= REPLACE(ColumnName,'''','')
where ColumnName LIKE ('''%''')

select distinct values of a replaced selected result

Good day all.
I'm facing a little problem with a mySql query. let's assume we have a table with a coulmn in which the values are pairs, but unified in the same field, so something like this:
id | serviceName
----+-------------
1 | foo - bar
2 | foo - doo
3 | foo - tep
4 | bee - bar
5 | bee - blo
I would like to select distinct the first part of serviceName, in this case foo, bee.
the desired output should be:
foo
bee
in the resultset.
what I've thought right now is something about making a SELECT DISTINCT a FROM REPLACE ( (SELECT serviceName as a FROM tableName), ' - ***', '')
but i'm not really sure if it is possible, and how to make it. I only would like to select the first part of the field, and I would like to take only distinct vlaues of it... it is possible? I need a right direction pointing,, I can make researches by my self.
thanks in advance.
Assuming that you always want to split on a dash -, this should work for you.
SELECT DISTINCT LEFT(serviceName, LOCATE('-', serviceName) - 2) FROM tableName;
SQLFiddle
IS this what you are looking at ?
select substring_index(serviceName,'-',1) as `first_part`
from test
group by `first_part`
DEMO

Count the frequency of each word

I've been trolling the internet and realize that MySQL is not the best way to get at this but I'm asking anyway. What query, function or stored procedure has anyone seen or used that will get the frequency of a word across a text column.
ID|comment
----------------------
Ex. 1|I love this burger
2|I hate this burger
word | count
-------|-------
burger | 2
I | 2
this | 2
love | 1
hate | 1
This solution seems to do the job (stolen almost verbatim from this page). It requires an auxiliary table, filled with sequential numbers from 1 to at least the expected number of distinct words. This is quite important to check that the auxiliary table is large enough, or results will be wrong (showing no error).
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(maintable.comment, ' ', auxiliary.id), ' ', -1) AS word,
COUNT(*) AS frequency
FROM maintable
JOIN auxiliary ON
LENGTH(comment)>0 AND SUBSTRING_INDEX(SUBSTRING_INDEX(comment, ' ', auxiliary.id), ' ', -1)
<> SUBSTRING_INDEX(SUBSTRING_INDEX(comment, ' ', auxiliary.id-1), ' ', -1)
GROUP BY word
HAVING word <> ' '
ORDER BY frequency DESC;
SQL Fiddle
This approach is as inefficient as one can be, because it cannot use any index.
As an alterative, I would use a statistics table that I would keep up-to-date with triggers. Perhaps initialise the stats table with the above.
Something like this should work. Just make sure you don't pass in a 0 length string.
SET #searchString = 'burger';
SELECT
ID,
LENGTH(comment) - LENGTH(REPLACE(comment, #searchString, '')) / LENGTH(#searchString) AS count
FROM MyTable;

MySql ordering problem

Consider the situation i have a table name "test"
-------
content (varchar(30))
-------
1
abc
2
bcd
-------
if i use order by
Select * from test order by content asc
i could get result like
--------
content
--------
1
2
abc
bcd
---------
but is there any way i could get the following result using query
--------
content
--------
abc
bcd
1
2
---------
To get by the collation, you can do by testing the first character... it appears you want anything starting with a numeric to be after anything alhpa oriented... something like the ISNUMERIC() representation by Ted, but my quick check doesn't show such function in MySQL.. So an alternative... because numerics in ASCII list are less than "A" (char 65)
Select *
from test
order by
case when left( content, 1 ) < "A" then 2 else 1 end,
content
Although I've seen different CONVERT() calls, I don't have MySQL available to confirm. However, in addition to the above case/when, you can add a SECOND case/when and call some UDF() or other convert function on the "content" value. If the string starts as alpha, it should return a zero value so the first case/when will keep them to the top of the list, then since all are all non-convertible to numeric would have a value of zero... no impact on the sort, then finally the content itself which will keep in alpha order.
HOWEVER, if your second case/when / convert function call DOES return a numeric value, then it will be properly sorted within the numeric grouping segment... which will then supercede that of the content... However, if content was something like
100 smith rd and
100 main st
they will sort in the same "100" category numeric value, but then alphabetically by the content as
100 main st
100 smith rd
100
this will do it:
SELECT *
FROM test
ORDER BY CAST(field AS UNSIGNED), field ASC
select * from sometable order by content between '0' and '9', content
Not sure on MySql but on SQL Server you can do this...
SELECT * FROM test
ORDER BY IsNumeric(content), content
The order of results is defined by collation used, so if you can find the right collation then yes.
http://dev.mysql.com/doc/refman/5.0/en/charset-collate.html
//edit
This is tricky. I've done some research and it seems that no currently available collation can do that. However there's also possibility to add new collation to MySQL. Here's how.

sql query to fetch tag information from single table

I have a table (Mysql) with different snippets with tags in a coloumns
table snippets
---------------
Id title source tag
1 "title" "srouce code" "Zend, Smarty"
2 "title2" "srouce code2" "Zend jquery"
3 "title3" "srouce code3" "doctrine"
I want to do a select statements so that I can build a tag clouds on my site.
Zend(2), smarty(1), jquery(1), doctrine(1)
Remember tages are not always sperated by space, some tages are separated by comma(,)
then I need a query to fetch all records with specific tages. which I think i can use something like that untill there is better solution for that.
Select * from snippets where tag like "%ZEND%"
looking for optimized solutions please.
create three tables!
table snippets
id | title | source_code
1 "title" "srouce code"
2 "title2" "srouce code2"
3 "title3" "srouce code3"
table tags
id | tag
1 "zend"
2 "smarty"
3 "doctrine"
4 "jquery"
table snippets_tags
id | snippet_id | tag_id
1 1 1
2 1 2
3 2 1
4 2 4
5 3 3
Tip: lower-case your tags because "Zend" and "zend" are the same
Now your tag cloud query should look like
SELECT tags.name, COUNT(snippets_tags.id) AS snippet_count
FROM tags LEFT JOIN snippets_tags ON snippets_tags.tag_id = tags.id
GROUP BY tags.id
Gives you a result like
name | snippet_count
zend 2
smarty 1
doctrine 1
jquery 1
To select all snippets belonging to a certain tag:
SELECT snippets.* FROM snippets, tags, snippets_tags
WHERE
snippets_tags.snippets_id = snippet.id AND
snippets_tags.tag_id = tags.id AND
tags.name LIKE '%zend%'
Have you thought about separating the source code and tags into separate tables?
Source Table
ID, Title, Source
1 "t1" "sc"
2 "t2" "sc"
3 "t3" "sc"
Tag Table
ID, Tag
1 "Zend"
2 "Smarty"
3 "jquery"
4 "doctrine"
SourceTagLink Table
SourceID, TagID
1 1
1 2
2 1
2 3
3 4
That way you have a unique list of tags that you can choose from, or add to.
You wont be doing any string parsing so your selects will be much faster. Sort of similar to how you assign tags to your post on this site.
EDIT
This is a function that I used to convert a multivalue string into a table with a single column it written is MSSQL but you should be able to convert it to mySQL
CREATE FUNCTION [dbo].[ParseString](#String NVARCHAR(4000), #Delimiter CHAR(1)=',')
RETURNS #Result TABLE(tokens NVARCHAR(4000))
AS
BEGIN
-- We will be seearching for the index of each occurrence of the given
-- delimiter in the string provided, and will be extracting the characters
-- between them as tokens.
DECLARE #delimiterIndex INT
DECLARE #token NVARCHAR(4000)
-- Try to find the first delimiter, and continue until no more can be found.
SET #delimiterIndex = CHARINDEX(#Delimiter, #String)
WHILE (#delimiterIndex > 0)
BEGIN
-- We have found a delimiter, so extract the text to the left of it
-- as a token, and insert it into the resulting table.
SET #token = LEFT(#String, #delimiterIndex-1)
INSERT INTO #Result(tokens) VALUES (LTRIM(RTRIM(#token)))
-- Chop the extracted token and this delimiter from our search string,
-- and look for the next delimiter.
SET #String = RIGHT(#String, LEN(#String)-#delimiterIndex)
SET #delimiterIndex = CHARINDEX(#Delimiter, #String)
END
-- We have no more delimiters, so place the remainder of the string
-- into the result as our last token.
SET #token = #String
INSERT INTO #Result(tokens) VALUES (LTRIM(RTRIM(#token)))
RETURN
END
Basically you call it like
ParseString('this be a test', ' ')
it will return a single column table
this
be
a
test
ParseString('this:be a test', ':')
returns
this
be a test
You could add a call to the function in an update trigger to populate the new tables to help you make selects much easier. Once the trigger is built, just do a simple update like the following
Update yourTable
Set Title = Title
That fill fire the trigger and populate the new tables and make everything much easier for you without affecting existing code. Of course youll need to replace all known delimeters with a single one for it to work.
Any new records added or modified will automatically fire the trigger.
At first you have to replace all characters like ',' space etc. with a fixed "separator" character like '#'. You could use a temporary table.
Then you have to create a function that loops over the fields and searches and counts the single tags.