I have an application with images stored in multiple categories, currently being stored by category ID in a column as a space separated list (eg. 1 5 23 2).
I have a query from a search filter, which is currently an array of IDs, (eg. 1 5).
Ideally, I'd find a solution using something like WHERE IN that would see if any of my array values exist in the stored column, although I don't see an easy solution.
At the moment I have to query all the images, bring them into PHP and check there, using "array_intersect". I see this as being a problem if I have 100,000s of images in the future to pull and then check.
Can anyone think of an elegant solution? The application is still in development, so I could arguably change the structure of my tables.
I think adding a map table would probably be best here which maps the image_id with the category_id.
refactor your database tables!!!
use sth like this:
table_image
id int
name text,
content text,
...
and a second table for the categories:
table_category
id int,
image_id int,
category int
this way, you can store categories in a separate table using foreign keys. now, you can do simple sql queries like
SELECT table_image.id FROM table_image, table_category WHERE table_image.id = table_category.image_id and table_category.category = $cat_arr[0] OR table_category.category = $cat_arr[1] ...
H Hatfield has the best answer. If you really must use a single column (which I do not recommend) you could store the categories as a comma separated list instead of spaces. You can then use the MySql function find_in_set, as such:
WHERE FIND_IN_SET('3', categoryListColumnName) > 0 OR FIND_IN_SET('15', categoryListColumnName) > 0
Using your current database design you could use an IN query:
WHERE categoryListColumnName LIKE '% 3 %' OR categoryListColumnName LIKE '% 15 %'
and add more OR's for every category you want to find. When using this query you have to make sure your list separated by spaces ends and starts with a space, otherwise it won't work.
Let me just reiterate, that these methods will work, but they are not recommended.
Related
i should migrate multiple columns of text into one column (in another database). Now i know that it sounds complicated, but i will try my best to explain it.
There is a table in mysql database called "products_desriptions". In that table we have columns like: descriptionDosage, descriptionAction, descriptionIndications and so on. What i want to do is to merge these columns into one column called "productDescription".
Here is an example of what i have done:
SELECT
CONCAT_WS('\ntest', action, Indications, staff, dosage) AS productDescription)
FROM
products_descriptions
WHERE
product_id = 123
So the the columns are being merged successfully.
The problem is that for each column there is a title in the frontpage, which is not being stored into the respective column. For example in the "dosage" column we have text like: "2xday, 14xweek" and so on. And on the frontpage what you can see is something like:
"DOSAGE:
2xday, 14xweek" and so on.
So for each column there is a hard codded title like this one, which i don't know how to get. I mean what i want to do is: to merge columns and respectively for each column i want a title to the respective text.
I am working on php, so maybe it is not possible to be done only by mysql. Maybe i have to do it with php, but has anyone got any idea what exactly should i do?
You can use concat function.
SELECT
CONCAT('\ntest', action, '\nIndictions:', Indications,'\nstaff:', staff,'\ndosage:', dosage) AS productDescription
FROM
products_descriptions
WHERE
product_id = 123
I have a PHP interface with a keyword search, working off a DB(MySQL) which has a Keywords field.
The way in which the keywords field is set up is as follows, it is a varchar with all the words formatted as shown below...
the, there, theyre, their, thermal etc...
if i want to just return the exact word 'the' from the search how would this be achieved?
I have tried using 'the%' and '%the' in the PHP and it fails to work by not returning all of the rows where the keyword appears in.
is there a better (more accurate) way to go about this?
Thanks
If you want to select the rows that have exactly the keyword the:
SELECT * FROM table WHERE keyword='the'
If you want to select the rows that have the keyword the anywhere in them:
SELECT * FROM table WHERE keyword LIKE '%the%'
If you want to select the rows that start with the keyword the:
SELECT * FROM table WHERE keyword LIKE 'the%'
If you want to select the rows that end with the keyword the:
SELECT * FROM table WHERE keyword LIKE '%the'
Try this
SELECT * FROM tablename
WHERE fieldname REGEXP '[[:<:]]test[[:>:]]'
[[:<:]] and [[:>:]] are markers for word boundaries.
MySQL Regular Expressions
if you also search for the commas, you can be sure you are getting the whole word.
where keywordField like '%, the, %'
or keywordField like '%, the'
or keywordField like 'the, %'
maybe I didn't understand the question properly... but If you want all the words where 'the' appears, a LIKE '%word%' should work.
If the DB of words is HUGE MySQL may fail to retrieve some of the words, that can be solved in 2 ways...
1- get a DB that support bigger sizes (not many ppl would chose this one tho). For example SQL Server has a 'CONTAINS' function that works better than LIKE '%word%'.
2- use a external search tool that uses inverted index search. I used Sphinx for a project and it works quite good. This is better if you rarely UPDATE the rows of the data you want to search from, which should be the case.
Sphinx for example would generate a file from your MySQL table and use this file to solve the search (it's very fast), this file should be re-indexed everytime you do a insert or update on the table, making it a much better solution if you rarely update or insert new rows.
It looks like you have a one to many relationship going on within a column. It might be better to create a separate table for keywords with a row for each keyword and a foreign key to whatever it is you're searching on.
Doing like '%???%' is generally a bad idea because the DB can't make use of an index so it will scan the whole table. Whether this matters will depend on the size of data you're working with but its worth considering up front. The single best way to help DB performance is in the initial table design. This can be tricky to change later.
I want to filter result of my SQL query. I want to select everything that has some specific text in some column.
Example:
SELECT * FROM categories WHERE (name
has 'abc' values in it's value ex.
MyabcCategory)
Also maybe it is not very good idea to do that in query, maybe it is better to get all and then filter array instead? But I don't know how to do that aether.
Use LIKE with % wildcard:
SELECT * FROM categories WHERE name LIKE '%abc%'
This will give you all the records that have abc somewhere in them.
You can learn more about it here :)
You want to use the LIKE operator, with % to match any character before and after your specific word :
select *
from categories
where name like '%abc%';
But note that doing so, MySQL will scan each line of the table, every time the query is executed... which might not be great if you have a lot of data.
If you're searching for some kind of text, you might either want to :
Use a FULLTEXT index, if you're working with MyISAM tables.
Or, use a solution that's separated from MySQL, with a specific indexing/search engine, such as Solr.
SELECT * FROM categories WHERE name LIKE '%abc%'
The Set up
This is more or less a follow up question to something I had previously posted regarding comma separated values (explode,implode). Here's the scenario which has been stomping me the last few days as I'm a noob--sorry for the lengthy post.
I'm passing a variable via the url (index.php?id=variable), I then check the database to find the rows containing that variable using
SELECT * FROM table WHERE column LIKE '%$variable%'
I'm using the wildcards because the results are a comma separated value with the variable appearing multiple times in the database.
So if we were assigning-- say schools to popular tv shows..my database is set up so that the user can assign more than one school to the tv show. IE.
South Park--> fsu, nyu ,mit
Archer --> harvard, nyu
Index.php?id=nyu would display Sourth Park & Archer.
The Problem
Because I am using Like '%variable%'
If I have the following:
South Park-->uark
Archer-->ua
index.php?=ua
Instead of just Archer showing, Southpark would also show.
Which makes sense due to the wildcards...but can anyone think of a way to do this achieving the results I want?..Is there any way to achieve more precise results using a comma separated value?..I'm completely stomped and will appreciate any help.
A better option is to create two other tables.
One table is the one you already have 'tv_shows' and the second table is the 'tags' table and the third table is the connection table.
Here is a sample:
CREATE TABLE tags(id INT, tag VARCHAR(200));
CREATE TABLE tv_tags(show_id INT, tag_id INT);
SELECT FROM tv_shows,tv_tags WHERE tv_shows.id=tv_tags.show_id AND tag_id IN (SELECT id FROM tags WHERE tag LIKE 'tag');
have you tried the REGEXP operator ? sth like
SELECT * FROM table WHERE column REGEXP('(^|,)%variable%(,|$)')
it can be slightly different if you have spaces between your tags, but the idea is here
I have a table called artists. Within it, there is a field for the artist name (artist_name). Then there is a field for SEO friendly artist name, we'll call it search_name.
I have over 40,000 artists in this table. So, I'd like to convert all artists names to search friendly. What is the best way to accomplish this? Not looking for code here, just ideas.
This is what I have thus far. I'm just not sure if I should call all 40,000 artists, loop through them and update?
// Does this artist name have any symbols, apostrophes, etc. If so, strip them out
// Does this artist have a space (the beatles)? If so, replace with + (the+beatles).
// insert into search field
As 40,000 records aren't that much, I'd grab all of them and loop through them in memory. By doing it in memory, unique checks should be pretty fast.
In the end, I'd just chain the commands together like: $query .= "UPDATE artists SET search_name = $generated_name[$i] WHERE id = $id[$i];".
By the way: I'd replace spaces with a minus.
You could go through and create a secondary table two columns wide (id, safe) and insert it from there.
Query Table 1
Convert artist names to safe names
Insert into Table 2
Use id of both tables to match them. This would only allow one to one matches though if id is the index, you may want to create a third column if you want multiple safe names for a single artist (id | artistID | artistName)
Please consider using some full-text search engine. For example, the free sphinx search - it's quite flexible, extremely fast and it does support word stemming.