Mysql - get last post from category - php

I have this structure (tables) of forum
I want to select last post (row from forum_post table) from category.
SQL so far:
SELECT * FROM table_post
WHERE topic_id = (SELECT MAX(id) FROM table_topic WHERE category_id = {$id})
ORDER BY id ASC LIMIT 1
Question: How to modify this select to achieve my goal?

Assuming that "last" means the biggest id, I would suggest order by and limit:
select fp.*
from forum_post fp join
forum_topic ft
on fp.topic_id = ft.id
where ft.category_id = $id
order by fp.id desc
limit 1;

Related

Select data from a MySQL table where some results from another table depends on a condition, if there are any

With a PHP code, I wish to order some MySQL results in a specific way.
I have two tables:
First table, called "post" with the following non-exhaustive content:
id
released_date
published_date
...
Second table, called "votes" with the following non-exhaustive content:
id
post_id
user_id
status
If a user votes for an existing post, a record is made in the "votes" table, inserting the post id as post_id and the user id as user_id. The status is 1 for an upvote and 2 for a downvote.
One important thing to keep in mind though: some posts might never receive any vote at all, and 0 occurrence would be found in the second table, for instance!
So, now on my first page I order my posts with their amount of votes (upvotes-downvotes) the following way, and it works fine:
$post_req = mysql_query('SELECT * FROM post
WHERE NOW() > released_date
ORDER BY ((SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 1)-(SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 2)) DESC, published_date DESC
LIMIT 0, 5');
But on the next page (i.e a new iteration), I need to continue where I left, in terms of votes. Before I do that, I save the votes amount of the last post of the first page to pass it to the next one, under the variable $last_post_votes.
Now, this where I struggle: I need to look for posts which have a lower amount of votes than this variable in a new request. As follows, my failing attempt:
$post_req_1 = mysql_query('SELECT * FROM post
WHERE NOW() > released_date
AND ((SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 1)-(SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 2)) < "'.$last_post_votes.'"
ORDER BY ((SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 1)-(SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 2)) DESC, published_date DESC
LIMIT 5');
And then I tried something like that, which failed too:
$post_req_1 = mysql_query('SELECT post.*,
((SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 1)-(SELECT COUNT(*) FROM votes WHERE votes.poste_id = post.id AND votes.status = 2)) AS all_votes
FROM post, votes
WHERE NOW() > post.released_date
AND all_votes < "'.$last_post_votes.'"
ORDER BY all_votes DESC, post.published_date DESC
LIMIT 5');
The problem is clearly the condition upon searching results from another table in the SELECT.
Any help is greatly appreciated!
Thanks a lot in advance! :-)
Lois
EDIT:
I managed to make it work as I wished, by using a condition directly in the ORDER BY itself. Not sure it's super proper, but it seems to work:
$post_req_1 = mysql_query('SELECT * FROM post
WHERE NOW() > released_date
ORDER BY ((SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 1)-(SELECT COUNT(*) FROM votes WHERE votes.post_id = post.id AND votes.status = 2)) < "'.$last_post_votes_passed.'" DESC, published_date DESC
LIMIT 5');
If your first statement works fine, why don't you continue with that?
Aou start with the LIMIT clause of LIMIT 0,5 which gives you the first 5 records of the resultset. If you increase the first parameter to LIMIt it will show you the next 5 records, and so on. No need to fiddle around with interim variables...
// first page
SELECT ... LIMIT 0,5
// seond page
SELECT ... LIMIT 5,5
// 10th page
SELECT ... LIMIT 45,5
See also http://dev.mysql.com/doc/refman/5.0/en/select.html
If i am not mistaken is this what you are looking for?
SELECT p.id, IFNULL(COUNT(v.id), 0) - IFNULL(COUNT(v2.id), 0) AS `Votes`
FROM
posts p
LEFT JOIN votes v on v.post_id = p.id AND v.status = 1
LEFT JOIN votes v2 on v2.post_id = p.id and v.status = 2
WHERE NOW() > p.released_date
ORDER BY `Votes` DESC;

Select from 2 tables and order by 1

I have 2 tables.
First:
TABLE Articles
ID
Second:
TABLE Viewcount
DATE DATE PK
ARTICLE_ID INT PK (MATCHES ID IN TABLE Articles)
NUMVIEWS INT
How do I select all IDs from table Articles and then order by NUMVIEWS (DESC) of Viewcount according to dates?
I then need to append the IDs from Articles that were not found in viewcount to the End of the results in no particular order.
I know it has to be some sort of Join but I can't figure it out..
try this
SELECT id from Articles a
LEFT JOIN Viewcount v
ON a.id = v.article_id
AND v.date = 'some date here'
ORDER BY v.numviews ,v.date desc
A simple join will suffice, yes:
SELECT a.id FROm Articles a LEFT JOIN Viewcount v
ON v.article_id = a.id
ORDER BY v.numviews desc, v.date
This should work:
SELECT * FROM `Articles` `a`, `Viewcount` `v`
WHERE `v`.`ARTICLE_ID`=`a`.`ID`
ORDER BY `v`.`NUMVIEWS` DESC
Replace SELECT * by SELECT `a`.`ID` to get only the Article IDs.
SELECT ID from (Articles JOIN Viewcount on Articles.ID = Viewcount.ID) ORDER BY Viewcount.NUMVIEWS, Viewcount.date

Sort a MySQL result based on total count of another result

I have tables tbl_posts and tbl_comments with primary keys post_id and comment_id respectively. I tried this code:
$allPosts=mysql_query("
select c.comment_id, post_id, count(*)
from post u,
comments c
where u.comment_id = c.comment_id
group by comment_id, post_id
LIMIT 10
");
but I have no clue what it does. How do I combine two tables so that the total comments determines the order of the listed posts from tbl_posts?
Try this, it's more readable if you separate per lines and work with joins
select c.comment_id, post_id, count(*)
from post u join comments c
on u.comment_id = c.comment_id
group by comment_id, post_id LIMIT 10
It looks like you have tables named tbl_comment and tbl_post but your query has them listed as just comment and post.
select c.comment_id, post_id, count(*)
from tbl_post u, tbl_comments c
where u.comment_id = c.comment_id
group by comment_id, post_id LIMIT 10
$allPosts=mysql_query("select c.comment_id, post_id, count(*) from tbl_post u, tbl_comments c where u.comment_id = c.comment_id group by comment_id, post_id LIMIT 10");
This just fixes the query so it runs, and does not address any content issues you may have, namely the group by on both (what I am guessing) are primary keys.
** EDIT **
To fix the sorting try:
SELECT tbl_post.comment_id, count(*)
FROM tbl_post, tbl_comments
WHERE tbl_post.comment_id = tbl_comment.comment_id
GROUP BY comment_id LIMIT 10
ORDER BY count(*)
Explanation of your SQL:
You are selecting column comment_id from table comments, column post_id from table post using a inner join, grouping by comment_id, post_id, with a limit of 10 results.
I would try:
$allPosts = mysql_query("SELECT * FROM
(SELECT c.comment_id, u.post_id, COUNT(*) AS 'count' FROM post u
LEFT JOIN comments c ON c.comment_id = u.comment_id
GROUP BY c.comment_id, u.post_id)
ORDER BY count DESC LIMIT 10");

MySQL query order the results in GROUP BY 3 Tables Count

I'm coding a listing system and I'm trying to get the posts ORDER by number of comments and votes FROM 2 tables.
Table1 : Lists => id, title, detail
Table2 : Votes => voteid, listid
Table3 : Comments => commentid, listid
WHERE MY Current query is
$q = mysql_query("SELECT * FROM zoo_leads
LEFT JOIN Votes ON Lists.id=Votes.listid
LEFT JOIN Comments ON Lists.id=Comments.listid
GROUP BY Lists.id ORDER BY Comments.listid DESC LIMIT 10
it is showing me results perfectly but ORDER BY is Lists.id Instead of number of votes and comments
Try:
SELECT *
FROM zoo_leads
LEFT JOIN votes
ON lists.id = votes.listid
LEFT JOIN comments
ON lists.id = comments.listid
GROUP BY lists.id
ORDER BY COUNT(votes.id) DESC,
COUNT(comments.id) DESC
LIMIT 10
That is because you have ORDER BY Comments.listid in your SQL statement.

A somewhat complex mysql query

I'm currently working on a news database website and I can't seem to create a query to select the 5 hottest news articles. The 2 tables of the database that are affected for this query are:
News - containing all news items (id, author, message, etc.)
Rates - containing all ratings on news items (id, news_id, rating, etc.)
Now my query should select 5 news_ids from the table Rates with the highest average rating and most votes ( so: ordered by AVG(Rating) and COUNT(*) I supposed ). I first tried to make my query as well get all info of these news_ids from the News table instantly ( using a WHERE id IN(--the query selecting the 5 hottest news_ids--) clause ) but that returned an error of my MySql Version not being cappable of using LIMIT inside of the WHERE IN clause sub-query.
Well, I hope you can help me out on the first query that has to select those 5 news_ids. The query I got as for now ( but not fully working ) is:
SELECT news_id FROM
(SELECT news_id, AVG(rating) AS average_r, COUNT(*) AS amt_r
FROM rates
GROUP BY news_id
ORDER BY average_r,amt_r
DESC LIMIT 5
) AS news_rates
or in content with the rest of my script:
$get_hot_news_ids = mysql_query("SELECT news_id FROM
(SELECT news_id, AVG(rating) AS average_r, COUNT(*) AS amt_r
FROM rates
GROUP BY news_id
ORDER BY average_r,amt_r DESC LIMIT 5) AS news_rates");
$first = 1;
while($news_id = mysql_fetch_assoc($get_hot_news_ids)) {
if(!$first) {
$hot_news_ids .= " ,";
}else{
$first = 0;
}
$hot_news_ids .= $news_id['news_id'];
}
//print_r($hot_news_ids);
$get_hot_news = mysql_query("SELECT * FROM news
WHERE id IN($hot_news_ids)
ORDER BY FIELD(id, $hot_news_ids)");
Are you sure both average_r and amt_r are both in descending order?
SELECT news_id FROM
(SELECT news_id, AVG(rating) AS average_r, COUNT(*) AS amt_r
FROM rates
GROUP BY news_id
ORDER BY average_r DESC, amt_r DESC
LIMIT 5
) AS news_rates
Try this:
SELECT TOP 5 N.id, N.author, N.message, AVG(R.rating) AS rate, COUNT(R.news_id) AS votes
FROM news N
INNER JOIN rates R ON N.id = R.news_id
GROUP BY N.id, N.author, N.message
ORDER BY rate, votes
You can use a join instead, which will allow the limit:
SELECT *
FROM news n JOIN (
SELECT news_id, AVG(rating) AS average_r, COUNT(*) AS amt_r
FROM rates
GROUP BY news_id
ORDER BY average_r,amt_r DESC
LIMIT 5
) top5 ON n.news_id = top5.news_id
ORDER BY top5.average_r,top5.amt_r
Note: You might want to change your query to a ORDER BY average_r DESC, amt_r DESC to get the highest rated items, instead of the lowest rated.

Categories