SQL Table Structure for news site - php

I want to make a fast table structure for news site with php and mysql. My database structure is ID, title, content, cat_ids (; separedet IDs of categories - ;5;10;15;20;), active, publish_date.
I want to make a fast query to select news from this table. Something like that:
SELECT id
FROM news
WHERE cat_ids LIKE '%;15;%'
AND active = 1
AND publish_date < NOW()
ORDER by publish_date DESC
LIMIT 0, 10
But if my table is 2-3GB the query is very slow. I need some ideas to make structure and make the select faster.

Instead of using cat_ids column, try creating a news_cats table with news_id and cat_id, and using this query:
SELECT id
FROM news JOIN news_cats ON news_id = id
WHERE cat_id = 15
AND active = 1
AND publish_date < NOW()
ORDER by publish_date DESC
LIMIT 0, 10

Some suggestions as below:
1) Create index on "active" field
2) Create index on "publish_date" field
3) Create separate table for category and news relation and remove "cat_ids" field from news table
New table might look like below:
news_category_ids
news_id
category_id
It can have multiple rows for each news_id, if news item falls in 3 categories, it will have 3 rows
Then use SQL like below:
SELECT news.id
FROM news INNER JOIN news_category_ids ON news.id = news_category_ids.news_id
WHERE 1
AND news.active = 1
AND news_category_ids.cat_id = 15
AND news.publish_date < NOW()
ORDER by news.publish_date DESC
LIMIT 0, 10

Related

How to get the last seven days data from mysql details in brief

Actually I have a table which name is posts and another table which name is newscount , in posts table there is four column id , title ,details, postingDate
and in newscount table there is three column which are id, postid, count ,
and in newscount table postid is the id of posts table id , I have saved data in posts table and also i have data in newscount table , for example - in posts table I have
id title details postingDate
1,title1,details1,somedate1
2,title2,details2,somedate2
3,title3,details3,somedate3
and in newscount table I have
id=1,postid=1,count=6
id=2,postid=2,count=5
id=3,postid=3,count=7
I want to select last two data from posts table which have maximum count , like if i select then it should show result like newscount.id=3,posts.id=3 which has max 7 count and newcount.id=1,posts.id=1 and its details
I have tried but it is showing only postsid 3detials not last two
SELECT * FROM (SELECT newscount.postId, newscount.count from newscount WHERE newscount.count = (SELECT max(count) FROM newscount ORDER BY id LIMIT 2) ) tempcounts INNER JOIN posts ON posts.id = tempcounts.postId WHERE posts.isActive=1 AND posts.postingDate >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY AND posts.postingDate < curdate() - INTERVAL DAYOFWEEK(curdate())-1 DAY ORDER BY posts.postingDate DESC limit 2
I couldn't run your query because you didn't give a complete table structure of your db, but you have at least 2 item to make them correct:
first:
you have this query, but it does not return two parameters(except in condition you have more than one row with max value)
(SELECT max(count) FROM newscount ORDER BY id LIMIT 2)
instead of that use this:
(SELECT count FROM newscount ORDER BY count DESC LIMIT 2)
the second: if you expect to get more than 1 row from a subquery in where clause you should use in instead of = operand

Mysql query to retrieve single image from an array of images?

Table to store array of Images:
`products` and `products_photos`
`products` includes only `id` field
`products_photos` includes `product_id` and `filename`
Table values:
products
--------
id-6
id-7
products_photos
---------------
6 - filename1
6 - filename2
7 - filename3
In these two table id 6 includes 2 images but i need to fetch only one image from that. How to write a query for that in mysql or laravel.
If you want to get the latest (last added) image of the product then you can do the following way
NOTE : Instead of *, use the precise columns so that your query performs faster.
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY products_photos.id DESC LIMIT 1;
If you want to get the first (old added) image of the product then you can do the following way
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY products_photos.id ASC LIMIT 1;
Updated : Query to get the list of all the records group
SELECT MAX(id) as id, photo_name FROM products_photos GROUP BY photo_name
In case if you have more than one columns and want to get the latest record for that too then go for this
Eg. Considering that your having description column and want to get the MAX (latest) content than use MAX, if you need oldest use MIN
SELECT MAX(id) as id, photo_name, MAX(description) as description FROM products_photos GROUP BY photo_name
You can give limit to your query to get single result
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY id LIMIT 1;
Which will give single image only for id = 6 product
For retrieve all data use group by
SELECT * FROM GemSellerPortal.products pr
LEFT JOIN GemSellerPortal.products_photos ph
ON ph.product_id = pr.id
GROUP BY pr.id

2 request by 1 MySQL

I wanna select from 2 tables.
In first table I want select all data.
In second table I want select only "name".
'edition' in first table it's 'id' in second table.
I wrote sql code, but it isn't work:
SELECT link, title, description, imgUri, vkCount, fbCount, twCount, edition
FROM articles
RIGHT JOIN SELECT name
FROM editions
WHERE id = articles.edition
ORDER BY (vkCount + fbCount + twCount) DESC
LIMIT 0, $count
Structure: http://i.imgur.com/bMcokCp.png
Looks pretty close but you have the JOIN syntax a little wrong. Use ON for a join and only one SELECT clause
SELECT link, title, description, imgUri, vkCount, fbCount, twCount, edition, name
FROM articles
JOIN editions ON id = articles.edition
ORDER BY (vkCount + fbCount + twCount) DESC
LIMIT 0, $count

How to find required unique result

I have two table 'topic' and 'subcategory'
I am using this query--
Select * from `subcategory` as s
Inner join `topic` as f
WHERE s.`Subcategory_id` = f.`Subcategory_id
My result shows like
Category_id Subcategory_id Post_id time
2 2.3 4 2012-12-01
1 1.5 5 2013-01-20
1 1.3 6 2013-03-18
There's also other columns... but all I want is to select the latest Post_id and Subcategory_id of one Category_id ... that means here Category 1 has two Subcategory it will select only the latest(here 1.3) and same result all the time for all Category when database will grown larger. What will be the next query or how could I change the existing query to gain my desired result?
SELECT Post_Id, Subcategory_Id from subcategory as s, topic as t where
s.Subcategory_id = t.Subcategory_id and time = (
SELECT Max(time) from subcategory as s1, topic as t1 where
s1.Subcategory_id = t1.Subcategory_id and s1.Category_id = s.Category_id
);
Something like that, I think, will work.
SELECT TOP 1 ... ORDER BY whatever column determines "the latest"
e.g.
SELECT TOP 1 ... ORDER BY TIME DESCENDING
Or in case of mysql:
SELECT ... ORDER BY TIME DESCENDING LIMIT 1
Join your topic table with following query:
SELECT s.* FROM subcategory s
Inner JOIN (SELECT s1.Category_id,
MAX(s1.time1) AS max_time
FROM subcategory s1
GROUP BY s1.Category_id) y
ON y.Category_id = s.Category_id AND y.max_time = s.time1

Advanced SQL query. Top 12 from each category (MYSQL)

I have a MYSQL5 database and PHP 5. I need a query for a games websites index page that only selects the first 12 from each category of games. Here is what I have so far.
$db->query("SELECT * FROM `games` WHERE status = 'game_published' AND `featured` = '1' ORDER BY `category`");
The php code then groups games of the same category together and displays them. But yeah it doesn't limit the number of games from each category like I want.
Here is exactly what the structure of the table looks like: i49.tinypic.com/aysoll.png
Here is a blog post which sounds like what I am trying to do: http://www.e-nformation.net/content/view/title/MySQL+Top+N+in+each+group+(group+inner+limit) But I can't make sense of it.
Any help is appreciated.
How about this?
SELECT * FROM (
SELECT
games.*,
#rn := CASE WHEN #category=category THEN #rn + 1 ELSE 1 END AS rn,
#category := category
FROM games, (SELECT #rn := 0, #category := NULL) AS vars
WHERE status = 'game_published' AND featured = '1'
ORDER BY category
) AS T1
WHERE rn <= 12
you could use UNION, if we are not talking about million of types...
pseudoSQL:
(SELECT * FROM table WHERE condition AND category = 'action' ORDER BY id LIMIT 10)
UNION
(SELECT * FROM table WHERE condition AND category = 'action' ORDER BY id LIMIT 10)
UNION
(SELECT * FROM table WHERE condition AND category = 'action' ORDER BY id LIMIT 10)
If you have array of categories in your PHP/ASP, you can generate this union on the fly.
More:
http://dev.mysql.com/doc/refman/5.0/en/union.html
EDIT:
Here's probably most useful resource: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
Use it well ^^
There may be a more elegant solution, but you can just execute a query for each category. First get a list of categories:
SELECT DISTINCT(category) FROM `games`;
Then take each of the results and query for 12 rows:
SELECT * FROM games WHERE status = 'game_published'
AND `featured` = '1' AND `category` = $category LIMIT 12;
Of course you need to add some kind of ranking row (and order by it) to get the top 12.
Note: There may be a way to do this with a single query, but it escapes me at the moment.
To use the technique from the posts you mention, you need a way to order the games. They're using article date. Then they select the number of older articles for that company, and say there can't be more than three.
If your games table has an auto-increment column called id, you can select the top 10 games per category like:
SELECT *
FROM games g1
WHERE status = 'game_published'
AND featured = '1'
AND 10 >
(
SELECT COUNT(*)
FROM games g2
WHERE g2.status = 'game_published'
AND g2.featured = '1'
AND g1.category = g2.category
AND g2.id > g1.id
)
The where condition says that there can't be more than 10 rows with the same category and a higher ID.

Categories