I have a question regarding MySQL. (&Php)
I have 3 tables:
Articles (id, title, content)
Articles_category (id,article_id,category_id,main,cposition)
Categories (id,title,content)
main - 0/1 (main category or not).
cposition - position on breadcrumbs - 1,2,3,... (or 0 - so it wont appear on breadcrumbs at all).
now, lets say i have 3 levels:
Home -> Articles -> News & Politics.
And I'm now going to - Articles.
I want Articles category to list all articles with their categories.
That means ->
Articles.
News & Politics
[article1]
[article2]
Military
[article1]
[article2]
-- (articles that their main category is Articles)
[article1]
[article2]
[article3]
How do i fetch this data and parse it one query (and if not possible in one, whats the best way to do it efficiently?)
try like
select c.title, a.title from Articles a
left join
Articles_category b
on a.id=b.article_id
left join
Categories c
on c.id = b.category_id
order by b.main, c.id, b.cposition
why not put the category_id in the article table?
Related
I'd like to build an administration page for my website, where I could use multiple checkboxes to store / updates many categories for a single post.
So I've created three tables:
POST Table (id (index, auto-increment, not null), subject, content)
CATEGORIES Table (id (index, auto-increment, not null), name)
POST_CATEGORIES Table (id (index, auto-increment, not null), id_cat (foreign key to CATEGORIES.id), id_post (foreign key to POST.id))
(This last table is building relations between the posts and its categories.)
So I'm trying to list the categories with multiple checkboxes. I'm doing this query, but it doesn't work as expected:
$select = $db->query('SELECT categories.id, categories.name, post_categories.id_cat AS fk_cat, post_categories.id_post AS fk_post, post.id AS post_id
FROM `categories`
LEFT JOIN post_categories
ON categories.id = id_cat
LEFT JOIN posts
ON post.id = id_post');
Result is i have a list of categories, but each category name is repeated depending on the number of posts having this category (e.g : if post 1 and post 2 have both category 1, category 1 will appear 2 times in my list).
EDIT :
Thanks for the replies, here is a sqlfiddle to see what's happening...
http://sqlfiddle.com/#!9/4c304/1
(I'm trying to display a list of categories. I won't select * from categories table because in a next step, i'd like the right categories to be checked when i edit a post.)
SELECT DISTINCT c.id
, c.name
, p.id post_id
FROM categories c
LEFT
JOIN post_categories pc
ON c.id = pc.id_cat
LEFT
JOIN posts p
ON p.id = pc.id_post
If i use GROUP BY categories.id, i don't have doubles anymore...
But it only keeps the first post which is "tagged" with the current category. I need to keep all those informations.
Maybe i should filter by a php query? Something like if count(category.id > 1) then only display the one where post_id = current post edit? (sorry if it's not clear, i feel a bit confuses :( )
I have a news list, with three categories. Let's say category1, category2, category3. Each article has a publish date. Now is it possible to get the list as follows:
most recent article in category1
most recent article in category2
most recent article in category3
second most recent article in category1
second most recent article in category2
second most recent article in category3
And if both category1 and category3 have one article left while category2 has run out of articles, the above list will be followed by:
third most recent article in category1
third most recent article in category3
I don't know if this is possible in mysql query. Please help!
If your category Number is limited you can loop it and in every loop, concat the sqls with UNION; the this sql:
"SELECT * FROM news WHERE 1 GROUP BY ".$category." ORDER BY publish_date DESC LIMIT ".$categoryCount." UNION ALL"
Note: Don't forget the substr the last "UNION ALL" string
I see questions like this so often, especially when it comes to web-based app content. I want the most recent X per Whatever. In this case, you want the most recent 3 articles. Instead of trying to structure queries that will be a pain to work with, I would suggest denormalizing the data for the news category table..
Add 3 columns for the most recent 3 articles. Then, add a trigger to the articles table. When an article is added to the table, do an update to the category table with it as the newest position, and shift the other two down so it is always rolling... Not positive on the trigger syntax, but something like the following for the update...
update Category
set ThirdArticleID = SecondArticleID,
SecondArticleID = FirstArticleID,
FirstArticleID = NewArticleIDJustAdded
where CategoryID = NewArticleCategoryID
Then, you can just do left-join per category and always have the "latest 3" something like
select
c.*,
A1.ArticleTitle as FirstArticle,
A2.ArticleTitle as SecondArticle,
A3.ArticleTitle as ThirdArticle
from
Category C
LEFT JOIN Articles A1
on C.FirstArticleID = A1.ArticleID
LEFT JOIN Articles A2
on C.SecondArticleID = A2.ArticleID
LEFT JOIN Articles A3
on C.ThirdArticleID = A3.ArticleID
Then you dont have any min(), max(), group by, order by desc, etc to worry about. You may want to pre-prime these category article entries, but after the entries get new articles, it will be self-synchronizing.
I am working on an e-commerce site from scratch using PHP and MYSQL. I have one table for categories, with a column for ID and a column for Parent_ID.
When displaying the products on categories.php, I have it set to display products where the Parent_ID OR the ID equals the $_GET['id'] field. But now I've run into a problem.
In my "Groceries" category, I have the "Cleaning & Home" subcategory, and under "Cleaning & Home" I have several categories like "Laundry", "Bathroom Supplies", etc.
My problem is that products in the third level don't display in the "Groceries" category, because technically the parent ID of "Laundry" is "Cleaning & Home". There will never be more than three levels (Parent, child, grandchild), but I would like categories in the grandchild level to also display in the parent level.
I've tried looking through MYSQL documentation and on other forums but so far no luck.
This requires a couple of joins to get to the top parent:
select c.*,
coalesce(cp2.id, cp.id, p.id) as MostParentId
from categories c left outer join
categories cp
on c.parent_Id = cp.id left outer join
categories cp2
on cp.parent_id = cp2.parent_id
where c.id = $_GET['id'] or cp.id = $_GET['id'] or cp2.id = $_GET['id'];
You can then compare the ids using or for a match to the parent category, subcategory, or whatever.
I have 3 tables : videos, categories, video_categories.
In videos, I have id, title, and other fields.
In categories, I have id and name.
In video_categories, I have id, video_id, and category_id.
One video can have multiple categories. So the video_categories table will be something like this.
id video_id category_id
1 1 1
2 1 2
3 1 3
If I want to have a list of videos and display their categories, which would be preferred?
Via PHP, call 1 query to get all videos, then loop on that to query to get each video's categories, and another query to get the category name. This will be really slow if the table is huge, right?
Via MySQL joins (need help on this). If I left join videos to video_categories, there will be 3 results of the same video_id. I can use GROUP BY or SELECT DISTINCT to get unique result, but how can I now get the categories' names?
My expected result will be something like this:
id title categories
1 Video1 pop, rock, jazz
For option 2, use GROUP_CONCAT. It will be ok
SELECT v.id, v.title, GROUP_CONCAT(c.name)
FROM videos v
INNER JOIN video_categories vc ON vc.video_id = v.id
INNER JOIN categories c ON vc.category_id = c.id
GROUP BY v.id, v.title
For Group_Concat() function , is the default separator. That's why I don't use it here.
Guessing the names of your other columns..
SELECT v.video_id, v.title, GROUP_CONCAT(c.category_name SEPARATOR ', ')
FROM videos v
LEFT JOIN video_categories vc ON vc.video_id = v.video_id
LEFT JOIN categories c ON c.category_id = vc.category_id
GROUP BY v.video_id, v.title
I am trying to have a section in a shop I am creating to display 5 random products, from that Category ID.
Firstly every category has an ID, and a set of Sub Catrgories, every Sub Cat has an ID, and within every Sub Cat is a number of products. Every Product also has an ID.
The Products table contains the ProductID and the SubCatID.
The SubCat Table Contains the SubCatID and The CatID
The Cat table contains only the CatID.
SO I need to display 5 random products by the CatID. I can get random products using a query similar to this:
$randomprod = mssql_query("SELECT TOP 5* FROM Products WHERE SubCatID = '1' ORDER BY NEWID()");
while ($echorand = mssql_fetch_array($randomprod)) {
I need a way to join the tables so I can display all products under a certain CatID however, and am finding it difficult because my Products table doesn't contain a CatID. I am aware there are a number of joins, but am fairly new to PHP and even newer to MS SQL. Can anyone tell me what join is best, or point me in the correct direction please?
Join products to sub categories, join sub categories to categories, like this:
SELECT TOP 5 Products.Name, SubCatergory.Name, Category.Name
FROM Products
INNER JOIN SubCatergory ON Products.SubCatID = SubCatergory.SubCatID
INNER JOIN Catergory ON SubCatergory.CatID = Category.CatID
WHERE Category.CatID = 1
ORDER BY NEWID()
I have used INNER JOIN in the above example.