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.
Related
Table categories:
id, name,
-------------
1 category1
2 category2
3 category3
4 category4
Table posts:
id, category, title
--------------------
1 1, 3 title1
2 4, 2 title2
3 1, 4 title3
I would like to have a show categories and counter posts in this category. In the category column in the table posts I IDs of categories, which are separated by ', '. How to do that is searched when category = category ID and show counter with a minimum of SQL queries.
You should fix your data structure to have one row per post and category. A comma-separated list is not a SQLish way to store data for many reasons. You should change this to a junction table.
Here are some reasons why:
Numbers should be stored as numbers and not strings.
Foreign key relationships should be properly defined, and you can't do that with a string to a number.
An attribute should contain one value.
MySQL doesn't have very good support for string processing functions.
Queries using the column cannot be optimized using indexes.
You should have a table called PostCategories for this information.
Sometimes, we are stuck with other peoples bad design decisions. If so, you can use a query such as:
select c.id, count(*)
from posts p join
categories c
on find_in_set(c.id, replace(p.category)) > 0
group by c.id;
I'm having an issue with finding related database rows that aren't specifically linked. Lets say we have 5 tables.
Products
Id | name
Product_tags
Id | product_id | tag_id
Tags
Id | name
Blog
Id | name
Blog_tags
Id | blog_id | tag_ids
So what I do is I grab a product, with this grab the tags this product has via the Product_tags table. Say I get something like this.
Product 101
Tags 123,124,125,126
Now I have this product page. The thing is, now I want to find a blog if it fits this product, but it doesn't need to have all tags that product has, product just needs to have all that blog has. So if blog has tags 124 and 126 it needs to match. Currently I save all the tags a blog has in one row (comma seperated) but this could be changed to save 1 tag per row if needed. If it was reversed I could do it but I need to check for a partial list in a different table.
Product 101
Tags 123,124,125,126
Should find
Blog 201
Tags 124,126
But not
Blog 202
Tags 120,124
I tried a few ways but I couldn't find a way to make this work, my closest attempt was a reverse like like this.
select * from Blog_tags where "'".implode(",",$tagIds)."'" LIKE concat("%", tag_ids, "%")
This sort-of worked but not for when the product had 1,2,3 and the blog only had 1,3.
This is untested and only from memory, so feel free to comment and tell me if it doesn't work.
First of all, normalize your tag list, do not use comma-separated string. You said this could be changed, so I'm going work to assume it's one row per tag, and the column name is tag_id.
Let's start by finding the blogs having some of the tags of you product 101.
SELECT *
FROM Blog
JOIN Blog_tags ON Blog.Id = Blog_tags.blog_id
WHERE tag_id IN (123,124,125,126)
GROUP BY Blog.Id
Now this query will also include blogs that have tags not in this list. So we need to remove them. I think something like that could work:
SELECT *
FROM (
SELECT Blog.id as blogId
FROM Blog
JOIN Blog_tags ON Blog.Id = Blog_tags.blog_id
WHERE tag_id IN (123,124,125,126)
GROUP BY Blog.Id
) as Blog_filtered
LEFT JOIN Blog_tags ON Blog_filtered.blogId = Blog_tags.blog_id AND Blog_tags.tag_id NOT IN (123,124,125,126)
WHERE Blog_tags.id IS NULL
GROUP BY Blog_filtered.blogId
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.
I have a quick question in regards to the approach to displaying products on an e-commerce package I am putting together. The problem that I facing is that I would like visitors of the site narrow their search.
For example, a use case would be:
A Visitor is currently browsing a season of products (eg. Summer Collections)
He / She should then be able to filter by category and brand within that season, so for example they might decide that they only want to see Pants from Clothes Galore.
The problem, I ma facing is that doing a single SQL query in order to find products that match all three of these factors (so the product is in the summer collection, is a pair of pants and made by clothes galore). The thing that makes this overly difficult is that products can be in multiple categories and seasons. So there would need to be an insane amount joins in order to grab the right result.
My database structure is as follows:
product -> product_category <- category
product -> product_season <- season
product <- brand (a product can only be made by one brand)
Hope someone can share their wisdom on this...
If you have a big catalog, you might be better to use Apache Solr ( http://lucene.apache.org/solr/ ). Otherwise, there are a few approaches.
You don't need the overhead and straight SQL isn't that insane, will perform reasonably well:
SELECT product.*
FROM product
LEFT JOIN product_category
LEFT JOIN category
LEFT JOIN product_season
LEFT JOIN season
WHERE season = ? AND category = ?
Alternatively, If you don't like the number of rows returned, you can aggregate the category and season into the product table (new columns), then use like queries to find things:
SELECT product.*
FROM product
where product.categories like '% category %'
and product.seasons like '% season %'
Select product.* From product
Left Join product_category On (product.product_id = product_category.product_id)
Left Join product_season On (product.product_id= product_season.product_id)
Left Join brand On (product.product_id = brand.product_id)
Where product_category.category_id = '$catId'
And product_season.season_id = '$seasonId'
And brand.brand_id = '$brandId'
Order By product.product_name
Ok, this is assuming product, product_category, product_season, brand, season, category are all tables. You should pass in the ID's of the season and category table directly from whatever you are using to filter the search by so that you don't have to join these tables.
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?