Basically what I have is an image gallery. Just tried to create one for learning purposes. What I have now is when he/she clicks on category the following mysql query to select the galleries is fired:
SELECT ID, name, gallery_thumb FROM galleries WHERE category1=$category_id OR category2=$category_id OR category3=$category_id ORDER BY ID DESC
This was just a fast and crappy solution which I threw together. Basically I want one gallery to appear in many categories. Here I made it that way as I create a gallery I can add it to three or less categories, therefore one gallery may appear in different cateogries. But this soultion isn't what I wanted.
Galleries table:
CREATE TABLE `galleries` (
`ID` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `description` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `category1` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `category2` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `category3` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `web_link` varchar(3000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `gallery_thumb` varchar(2000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `reg_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`ID`) )
The category2 and category3 will be unnecessary and removed if I get the functionality I want working.
Tags table:
CREATE TABLE `gallery_tags` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `tag_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`ID`) )
Tags and galleries reference table:
CREATE TABLE `gallery_tag_reference` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `gallery_id` int(11) NOT NULL, `tags_id` int(100) NOT NULL, PRIMARY KEY (`ID`) )
I added a tags functionality. As I create a gallery now I can add as many tags as I like to the gallery. Now the gallery will have only one main category and many tags tied to it. But I want the gallery to appear in other categories as well based on the tags which I added when I created the gallery. The categories will have one or more tags predefined to them. What I want to do now is when visitor clicks on the category the same data would be selected which was before only the query filtering part would be different.
Example:
Category1 will have tags: car, blue, shiny
The gallery1 will have tags: blue, red, fast.
The gallery1 do not belong to category1 but because it has a tag "blue" added to it in the table "gallery_tags" it appears in the result of the query executed when visitor clicked on category1 button.
Example2:
Category1 will have not tags.
Category2 will have not tags.
Category3 will have not tags.
Category4 will have predefined tags: yellow, red.
Category5 will have predefined tags: tall, high.
Gallery1 will have no tags but it belongs to Category1.
Gallery2 will have no tags but it belongs to Category2.
Gallery3 will have tags: yellow, tall, field
Gallery3 belongs to Category3.
When visitor clicks on Category4 button selected are galleries which belong to Category4 AND the galleries which have tags "yellow" or "red". Because here we have no galleries belonging to Category4 but we have gallery3 which has tag yellow and the Category4 also has predefined tag "yellow" gallery3 is showed in Category4 when cliked on.
The same is with Category5. It does not have any galleries belongig to it directly but because gallery3 has a tag "tall" tied to it and Category5 also has predefined tag "tall" the gallery3 is shown also in Category5.
I hope I described it cleary what I want to achieve. As I am not very experienced in MySQL I have trouble putting the necessary query together. I hope someone will help!
OK, so you basic unit of selection is the tag and the categrory - let's start by creating tables for them
CREATE TABLE tags (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
-- Maybe some other things you want? Tag description?
UNIQUE INDEX name
);
this gives us a tags
table, we can fill it with
INSERT INTO tags(name) VALUES
('car'),('blue'),('shiny'),('red'),('fast'),('yellow'),('tall'),('high'),('field')
;
basically the same thing happens with the categories:
CREATE TABLE categories (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
-- Maybe some other things you want? Description?
UNIQUE INDEX name
);
INSERT INTO categories(name) VALUES
('cars'),('people'),('colors'),('landscapes'),('misc')
;
and now we can look at the galleries:
1:n
relationship from
the POV of the category, so we need a pointer field in the n
-side
of the relation, the galleries. I do not use foreign keys here for
brevity only, you are strongly encouraged to consider their use.So we do:
CREATE TABLE galleries (
id int(11) PRIMARY KEY AUTO_INCREMENT,
name varchar(100) NOT NULL,
category` INT NOT NULL,
-- the other fields you want: description, web_link, gallery_thumb,reg_time
UNIQUE INDEX(name)
)
Mind the data type INT
for the category: It will link to the primary key of the categories table, which is INT
also.
And we may not forget the join tables:
CREATE TABLE galleries_tags (
gallery INT,
tag INT,
PRIMARY KEY(tag, gallery),
KEY(gallery)
);
CREATE TABLE categories_tags (
category INT,
tag INT,
PRIMARY KEY(tag, category),
KEY(category)
);
The tag
field of type INT
will link these join tables to the id
field of the tags
table, while the gallery
resp. category
fields will link to the id
field of the respective tables.
Again we fill the tables with INSERT
queries. (To lazy to write them out)
Now you have your data in the database, time to get it out again:
You usecase: User clicks on a category, you want to select the galleries, that have
This is quite easy, but it needs a little thinking:
categories
category
fieldLEFT JOIN
, if you don't want to miss category-only selections, but this will kill your performance. So you select separate and UNION
the resultsAssuming your user selected category 4:
SELECT * FROM galleries WHERE category=4
UNION
SELECT categories.*
FROM galleries
INNER JOIN galleries_tags ON galleries.id=galleries_tags.gallery
INNER JOIN categories_tags ON categories_tags.tag=galleries_tags.tag
WHERE categories_tags.category=4
and Bob's your uncle.
What does this query do? the first part is simple, thesecond part selects those galleries, that
INNER JOIN galleries_tags ON ...
)INNER JOIN categories_tags ON ...
)id
4