I wanted to know how can you search in tags p.s.
I have a table where there is a column for tags "bar,barmen,drink".
In search for example people search for barmen drink, how do I match this, I tried
LIKE, INSTR() but no luck, the point is that tags column content doesn't have spaces between.
It's like "bar,barmen,drink" not like "bar, barmen, drink"
Any help..?
Why not have a separate tags table, with
id int(11) auto_increment
post_id int(11)
tag text
Then, have one tags row for each tag.
This is a problem inherent with this type of design. Short of changing how you store the data, you'd have to do a search like this:
SELECT * FROM my_table WHERE CONCAT(',', tags, ',') LIKE '%,bar,%';
EDIT: Actually, I just double-checked, and you can use regexp like so:
SELECT * FROM my_table WHERE tags REGEXP '[[:<:]]bar[[:>:]]';
Which should be quite a bit faster.
Related
Hello everyone as the topic says I am looking for alternative or advanced using of "LIKE".
I have column which contains a row of words p.e. "keyword1,keyword2,another_keyword" and when I use
$sql = mysql_query("SELECT * FROM table WHERE `column` LIKE '%keyword1%' ");
It hardly find it p.e. this example works but when i try to find shorter strings it has problems and sometimes it does not find anything.
I tried put a whitespace after comas and it helped but if there is a way where I can search for match with this specification of column I would be happy.
You may move keywords into individual table.
Or you can use SET field type, if the list of your keywords don't change.
Storing comma separated list of your words is a bad idea example using like in your scenario is hard to find the exact work in comma separated list instead you can add new table which relates to your current table and store each the word in a new row with the associated identity like
table1
id title
1 test1
2 test2
kewords_table
table1_id word
1 word1
1 word2
1 word3
and query will be
select t.*
from table1 t
join kewords_table k
on(t.id = k.table1_id)
where k.word = 'your_keyword'
If you can't alter your structure you can use find_in_set()
SELECT * FROM table WHERE find_in_set('your_keyword',`column`) > 0
try something like this:
SELECT * FROM tablename
WHERE column LIKE '%keyword1%'
OR column LIKE '%keyword2%';
for more info see here:Using SQL LIKE and IN together
MySQL allows you to perform a full-text search based on very complex queries in the Boolean mode along with Boolean operators. This is why the full-text search in Boolean mode is suitable for experienced users.
First You have to add FULLTEXT index to that perticuler column :
ALTER TABLE table_name ADD search_column TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, ADD FULLTEXT search_column (search_column);
Run following query for searching :
SELECT * FROM table WHERE MATCH(search_column) AGAINST("keyword1")
for more info see here : https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html
I have a table that contains 3 text fields, and an ID one.
The table exists solely to get collection of ID's of posts based on relevance of a user search.
Problem is I lack the Einsteinian intellect necessary to warp the SQL continuum to get the desired results -
SELECT `id` FROM `wp_ss_images` WHERE `keywords` LIKE '%cute%' OR `title` LIKE '%cute%' OR `content` LIKE '%cute%'
Is this really enough to get a relevant-to-least-relevant list, or is there a better way?
Minding of course databases could be up to 20k rows, I want to keep it efficient.
Here is an update - I've gone the fulltext route -
EXAMPLE:
SELECT `id` FROM `wp_ss_images` WHERE MATCH (`keywords`,`title`,`content`) AGAINST ('+cute +dog' IN BOOLEAN MODE);
However it seems to be just grabbing all entries with any of the words. How can I refine this to show relevance by occurances?
To get a list of results based on the relevance of the number of occurrences of keywords in each field (meaning cute appears in all three fields first, then in 2 of the fields, etc.), you could do something like this:
SELECT id
FROM (
SELECT id,
(keywords LIKE '%cute%') + (title LIKE '%cute%') + (content LIKE '%cute%') total
FROM wp_ss_images
) t
WHERE total > 0
ORDER BY total DESC
SQL Fiddle Demo
You could concatenate the fields which will be better than searching them individually
SELECT `id` FROM `wp_ss_images` WHERE CONCAT(`keywords`,`title`,`content`) LIKE '%cute%'
This doesn't help with the 'greatest to least' part of your question though.
I'm building a search on my site and I noticed it doesn't work when you enter more than one word into the search. Here's the gist of the query:
SELECT * FROM `blog` WHERE `content` LIKE '%$keyword%' OR `title` LIKE '%$keyword%' ORDER BY `id` DESC
The weird things is that when I test the query in phpMyAdmin it returns the expected results. On my website however, no results are found.
I tried replacing spaces in the keyword with %s, but that didn't change anything.
The problem is that LIKE does pattern matching rather than actually search for keywords. You should create a fulltext Index on your database columns and use WHERE MATCH keywords AGAINST column. That will properly search for all keywords in any order and be a lot faster anyway.
I just tried this in my database and using LIKE in the query is more than 66 times as fast than using MATCH with fulltext index. I'm using two tables which are "connected" to each other. One is tags and the other one is products.
So what I did was that I added a fulltext index to the tag column in the tags table and performed the match against that column. The query than joins the products and then spits out some data about the item. That took about 4 seconds with ~3000 products & ~3000 tags.
I then tried it by first exploding the search string by whitespaces, and then imploding the result with %' OR tags.tag LIKE '%. This took about 0,06 seconds with the same amount of products and tags.
I am struggling to find a solution to this. I have tags that are inserted into the database in this form
mytags=firsttag, secondtag, thirdtag
On the single page I need to show related items based on these tags aso I am using
SELECT * FROM posts WHERE tags LIKE \"%$mytags%\" ORDER BY views DESC LIMIT 5"
However this doesn't work much as it only searches for posts that have the exact same tagline (firsttag, secondtag, thirdtag) and not the posts that their tag contain one of the tags (firsttag, anothertag, andanothertag).
I thought of exploding mytags and then search using the first tag in the array, but this doesn't work very good.
Does anyone know an effective method of searching?
Why don't you use separate table for post tags keeping? I mean for example table 'posts', table 'tags' and relation table 'posts_tags'.
Here is structure of 'posts':
id
title
content
Here is structure of 'tags':
id
tag_name
And here is structure if 'posts_tags':
id
post_id
tag_id
This is scheme of 'many to many' relationship model. And you can now simply find tags or/and posts through JOIN operator.
This is not a propper way to do it. Your database is not normalised. In short, it is impossible to do what you want, and even if it is, that'd be highly ineffective.
You have to create another table - Tags, and then another one to represent the connection of tags to Posts let's say TagsPosts, everything propperly indexed.
You might want to look into find_in_set() but also, I would highly recommend to normalize your database and use a proper structure.
You should always keep your data normalised (one piece of data in each column). There's a solution to this problem using two tables; one for tags and one for posts and a MySQL LEFT JOIN. Below is a very minimal example.
Table posts
id int(11) Auto Increment
title char(255)
Table tags
id int(11)
postid int(11)
tag char(64)
Query to search for posts with tags containing firstpost
(important)
SELECT p.title FROM posts p
LEFT JOIN tags t
ON t.postid=p.id
WHERE t.tag LIKE '%firstpost%'
Sample data
INSERT INTO `posts` (`id`, `title`) VALUES
(1, 'Post number 1'),
(2, 'Another post'),
(3, 'Third post');
INSERT INTO `tags` (`id`, `postid`, `tag`) VALUES
(0, 1, 'first_post'),
(0, 1, 'firstpost_secondtag'),
(0, 2, 'secondpost_firsttag');
As I said above, this is a very minimal example. The most important bit here is the use of LEFT JOIN and a separate tags table. It should be obvious to you that you simply replace firstpost in the LIKE statement with a PHP variable.
I have a mysql table with these columns: id, text, keywords.
ID is an id. Text is a title. Keywords is a list of tags in this format: tag1 tag2 tag3.
How would I go about getting a list of the most used keywords in the column? Eg. if I wanted to build a tag cloud from all the items in the table.
There are ways to do what you want. But it won't be simple. The way you have organized your keywords in this database is going to cause quite a few headaches. You should try to normalize the data.
Perhaps instead of this:
id text keywords
1 bob he she it
2 thing white yellow hello
Have an separate table for the keywords:
id keyword
1 he
1 she
2 white
2 yellow
That way, it would be a much simpler matter to find what you want:
select count(keyword) as num from `keywords` group by keyword order by num desc
A simple way would be to create an array where each key is tag#. The value of each of those keys is the number of times tag# appears in the database; this would involve traversing through each tag in the database.
You might be better off normalising your database tables. Maybe something like this:
Items table : id, text
Tags table : id, text
items_tags table: item_id, tag_id
This way you can associate multiple tags with each item, and queries for tag counts become easy.