I have 2 tables(I'm making kind of forum) I would like to sort topics order by last post that has been written(order by row 'posts.date_written'). I was trying to do it by myself but I couldn't get it working.
Topic table:
ID|id_subforum|owner_id|owner|title|description
Posts table:
ID|id_subforum|id_topic|by|description|date_written
Can somebody show me how should this SQL look like?
SELECT t.*
FROM topics AS t
LEFT JOIN (
SELECT id_topic, id_subforum, MAX(date_written) AS last_date
FROM posts
GROUP BY id_topic, id_subforum
) AS p
ON t.id = p.id_topic AND t.id_subforum = p.id_subforum
WHERE t.id_subforum = '$forumId'
ORDER BY last_date DESC
Related
Ok, so this is not a new problem to me but since sophisticated SQL queries is not among my best talents I would typically break it apart. Still, I'm pretty sure a single query is possible and this time around I feel like doing it right but I simply can't put my finger on it. The following is as far as I could go:
SELECT forums.forum, forums.description, topics.forum_id,
(SELECT COUNT(id) FROM topics WHERE forum_id = forums.id) AS num_topics,
(SELECT COUNT(id) FROM posts WHERE topic_id = topics.id) AS num_posts,
MAX(posts.id) AS last_post
FROM forums
LEFT JOIN topics ON topics.forum_id = forums.id
LEFT JOIN posts ON posts.topic_id = topics.id
LEFT JOIN users ON users.id = posts.author_id
So I select forum id, forum name, short description and forum id aqcuired from topics table because the column name is unique by default. Then I use subqueries to count the sum total of topics and posts per forum (is there any other way to do it?). And then comes the most tricky part. I can get the last post per forum (MAX(post.id)) but try as I might I can't get the topic id and name for it, as well as the post author, which I never even got close to. Doing something like (SELECT topic_id FROM posts WHERE id = last_post) is not working, of course, and I don't understand why.
This will not be quick
SELECT forums.
forum, forums.description, topics.forum_id,
(SELECT COUNT(id) FROM topics WHERE forum_id = forums.id) AS num_topics,
(SELECT COUNT(id) FROM posts WHERE topic_id = topics.id) AS num_posts,
MAX(posts.id) AS last_post,
(SELECT topic_id FROM posts ORDER BY id DESC LIMIT 1) LAst_topic_id,
(SELECT topic_name FROM topics WHERE id = (SELECT topic_id FROM posts ORDER BY id DESC LIMIT 1)) LAst_topic_name
FROM forums
LEFT JOIN topics ON topics.forum_id = forums.id
LEFT JOIN posts ON posts.topic_id = topics.id
LEFT JOIN users ON users.id = posts.author_id
Or if the last id is not really the last id from the post tables
SELECT
forum,description,forum_id,num_topics,num_posts,last_post,
(SELECT topic_id FROM posts WHERE id = last_post) LAst_topic_id,
(SELECT topic_name FROM topics WHERE id = (SELECT topic_id FROM posts WHERE id = last_post)) LAst_topic_name
FROM
(SELECT
forums.forum, forums.description, topics.forum_id,
(SELECT COUNT(id) FROM topics WHERE forum_id = forums.id) AS num_topics,
(SELECT COUNT(id) FROM posts WHERE topic_id = topics.id) AS num_posts,
MAX(posts.id) AS last_post
FROM forums
LEFT JOIN topics ON topics.forum_id = forums.id
LEFT JOIN posts ON posts.topic_id = topics.id
LEFT JOIN users ON users.id = posts.author_id) t1;
I want to get all id with the max id2 value.
I tried just to get the max id2 but then it will looks for the overall maximum value of id2 inside the table , but i want to get all maxiums of id.
So I got 2 tables - table news and table topics.
Everytime I create a news there will automaticly create a topic. Now I want to show all news - and the current number of replies. So first step - topicid = id.
and every topic got id and id2.
id is the topic id
and id2 is the reply id
so if i got topic (a) with 4 comments it would look like
(id(1),id2(1))
(id(1),id2(2))
(id(1),id2(3))
(id(1),id2(4))
now a new topic (b) with 6 comments
(id(2),id2(1))
(id(2),id2(2))
(id(2),id2(3))
(id(2),id2(4))
(id(2),id2(5))
(id(2),id2(6))
so i want to get ((id(1),id2(4)) and (id(2),id2(6)))
<?php
$news = "SELECT n.titel,n.datum,n.typ_news,n.news,n.verfasser,n.time,n.topicid,
t.id, t.id2 FROM news n LEFT JOIN topics t ON t.id = n.topicid
ORDER BY n.id DESC LIMIT 10 ";
$neuenews = mysql_query($news);
while ($dnews = mysql_fetch_array($neuenews))
{
echo " <div style='text-align:center;color:#FFFFFF;font-size: 24px;'> "
.$dnews['titel'].
"a";
}
Ehm this was the solution :
$dn1 = mysql_query('select c.id, c.name, c.description, c.position,c.bild,
(select count(t.id) from topics as t where t.parent=c.id and t.id2=1) as topics,
(select count(t2.id) from topics as t2 where t2.parent=c.id and t2.id2!=1) as replies
from categories as c group by c.id order by c.position asc');
Try this:
SELECT n.titel,n.datum,n.typ_news,n.news,n.verfasser,n.time,n.topicid, t.id, MAX(t.id2) AS id2
FROM news n
LEFT JOIN
topics t
ON t.id = n.topicid
GROUP BY n.topicid
ORDER BY n.id DESC LIMIT 10
It looks like the specified/desired result from the topics table is accomplished by a query like this:
SELECT t.id
, MAX(t.id2) AS max_id2
FROM topics t
GROUP BY t.id
OPTION 1
To get that result joined to rows in news, you could use that query as an inline view in your query in place of the topics table. For example:
SELECT n.titel
, n.datum
, n.typ_news
, n.news
, n.verfasser
, n.time
, n.topicid
, t.id
, t.max_id2
FROM news n
LEFT
JOIN ( SELECT m.id
, MAX(m.id2) AS max_id2
FROM topics m
GROUP BY m.id
) t
ON t.id = n.topicid
ORDER BY n.id DESC LIMIT 10
OPTION 2
If id is UNIQUE (or PRIMARY KEY) in news table, then you may be able to eliminate the inline view, do a join to topics, and do a GROUP BY n.id, something like this:
SELECT n.titel
, n.datum
, n.typ_news
, n.news
, n.verfasser
, n.time
, n.topicid
, t.id
, MAX(t.id2) AS max_id2
FROM news n
LEFT
JOIN topics t
ON t.id = n.topicid
GROUP BY n.id
ORDER BY n.id DESC LIMIT 10
Not clear enough. what are the columns id= 1 id2=1 etc.? Two tables each with 2 columns? No clue.
I'm thinking something on the order but No clue what you actually want.
SELECT `MAX(`id2`) as MAX,`id` FROM `News` WHERE `id2` = `MAX`
I am currently (trying to) develop a forum. Now I've run into a small obstacle. I've four tables in my database; "categories", "forums", "topics" and "replies". They all have an id, a parent id and a name.
My problem is now how I should store and get the amount of topics and replies for each category and forum. At first I thought of saving all the topics and replies in every category and forum, as well as save all the replies in every topic.
But that is something I'd rather try to avoid seeing as I have to do 1x insert and 3x update for every reply made; 1 to category, 1 to forum, 1 to topic and finally the reply itself, an insert.
So instead I thought if it somehow was possible (and if so how) to make a query with COUNT, GROUP BY and INNER JOIN
Something along the line
SELECT *
FROM `categories`
JOIN (COUNT ( * )
FROM `topics`
GROUP BY `parent_id`
WHERE `parent_id` = `categories`.`id`) as `amount_of_topics`
JOIN (COUNT ( * )
FROM `topics`
GROUP BY `parent_id`
WHERE `parent_id` = `topics`.`id`) as `amount_of_replies`
Just that I don't get it work the way I want to at.
So to fetch all replies and count them for a specific forum, the connection replies and forum got is that parent_id of the reply belongs to a topic whos parent_id belongs to a forum.
I'm not sure if I understand your question correctly but if you just want the count of topics and replies for a specific forum (provided the categories belong to a forum and not the other way around) you would go with a query along this line:
SELECT forums.ID as forum_id
, forums.name as forum_name
, Count(topics.ID) AS count_of_topics
, Count(replies.ID) AS count_of replies
FROM forums
LEFT JOIN categories ON forums.ID = categories.parent_id
LEFT JOIN topics ON categories.ID = topics.parent_id
LEFT JOIN replies ON topics.ID = replies.parent_id
GROUP BY forums.ID, forums.name, categories.ID, categories.name;
If you are looking for the count of topics & replies by categories, use:
SELECT categories.ID as category_id
, categories.name as category_name
, Count(topics.ID) AS count_of_topics
, Count(replies.ID) AS count_of replies
FROM categories
LEFT JOIN topics ON categories.ID = topics.parent_id
LEFT JOIN replies ON topics.ID = replies.parent_id
GROUP BY forums.ID, forums.name, categories.ID, categories.name;
Hope that helps but if that's not what you are trying to achieve, please add precisions to your question.
I think this is the query you want:
SELECT categories.*, `amount_of_topics`, `amount_of_replies`
FROM `categories` JOIN
(select `parent_id`, COUNT ( * ) as `amount_of_topics`
FROM `topics`
GROUP BY `parent_id`
) tp
on tp.`parent_id` = `categories`.`id`) JOIN
(select `topics`.`id`) , COUNT ( * ) as `amount_of_replies`
FROM `topics`
GROUP BY `topics`.`id`
) ti
on tp.`parent_id` = ti.`id`
The idea is to create separate subqueries for each of the topic groups you want, and then to join them together.
I have two tables called 'events' and 'topics' each table can have many comments.
What I need to do is list all the events and topics with the amount of comments for each row. I've managed to return all the topics, which works great but I don't know how I can add the events table to the MySql. The comments and events table fields are listed below. Can anyone help me with this query?
Events:
ID
Event_Name
Comments:
post_id <-- the releated id for either the events or topics table
table <-- The table that the row belongs to so either topics or events
SELECT
t.id, t.title, c.created_at,
IF(ISNULL(c.allComments), 0, c.allComments) AS totalComments
FROM topics AS t
LEFT OUTER JOIN (
SELECT created_at, post_id, COUNT(*) AS allComments
FROM comments
GROUP BY post_id
) AS c ON c.post_id = t.id
ORDER BY tc.created_at DESC, c.allComments DESC
Sounds like events and topics should be the same table.
Still, I think we can do this with a UNION. Events and Topics have the same columns i hope? (Or at least the same important ones?)
(SELECT c.table as event_or_topic, e.*, count(C.table), MAX(C.created_at) as latest_c
FROM events E LEFT JOIN comments C on (C.post_id = E.id)
WHERE C.table = 'Events'
GROUP BY C.post_id)
UNION
(SELECT c.table as event_or_topic, t.id*, count(C.table), MAX(C.created_at) as latest_c
FROM topics T LEFT JOIN comments C on (C.post_id = E.id)
WHERE C.table = 'Topics'
GROUP BY C.post_id)
ORDER BY latest_c
Notice that the ORDER BY applies to the whole UNION, not the individual SELECTs.
The use of LEFT JOIN should allow those rows without Comments to still show. I think the problem is that we have parts of our select dependent on comments (ie - C.table, ordering on last comment, etc). The count should be fine - will just be zero if there are no comments.
You might need to change the SELECT part slightly. I'd like to display C.table so you know whether a row is a topic or event, but im afraid it might screw up the count. Do you need anything from comments besides the count? You use some columns other than post_id and table in your query that you neglected to explain in your question.
You still have columns I don't know what they are, like Comment's zoneTable
Try this:
SELECT
t.id, t.title, c.created_at, COUNT(c.allComments) AS totalComments
FROM topics AS t LEFT JOIN comments c ON t.id=c.post_id
GROUP BY t.id ORDER BY tc.created_at DESC, c.allComments DESC
If I understand your question you have 3 tables:
-Events
-Topics
-Comments
If that is true something like this should extract all the data:
SELECT *
FROM events,topics
LEFT JOIN comments ON post_ID = ID
ORDER BY date DESC
Hope i'm along the right lines!
W.
I've got it working. If anyone knows of a better and an efficient way of doing this, then please let me know:
(SELECT t.id, t.title, tc.dateCreated AS commentDate,
IF(ISNULL(tc.allComments), 0, tc.allComments) AS totalComments,
t.LastActive as dateChanged
FROM Events AS t
LEFT OUTER JOIN (
SELECT MAX(created_at) AS dateCreated, post_id,
COUNT(*) AS allComments
FROM comments
GROUP BY post_id
) AS tc ON tc.post_id = t.id)
UNION
(SELECT t.id, t.title, tc.dateCreated AS commentDate,
IF(ISNULL(tc.allComments), 0, tc.allComments) AS totalComments,
t.LastActive as dateChanged
FROM topics AS t
LEFT OUTER JOIN (
SELECT MAX(created_at) AS dateCreated, post_id,
COUNT(*) AS allComments
FROM comments
GROUP BY post_id
) AS tc ON tc.post_id = t.id)
ORDER BY commentDate DESC, dateChanged DESC, totalComments DESC
On the home page of my website I want to display the latest posts to the forum however I don't want to show the same topic twice. How can I modify the code below to do this?
http://punbb.informer.com/wiki/punbb13/integration#recent_10_posts
Basically show the latest posts, but only once for each forum topic/thread.
Add a condition to keep only records where the post is the last post in the topic:
WHERE p.id = (
SELECT pp.id
FROM posts AS pp
WHERE pp.topic_id = t.id ORDER BY pp.posted DESC LIMIT 1
)
If you want only one value per topic, you could group by topic, and from each topic select the most recent post. Then, you could choose the top 10 topics.
I'll write it in SQL, and you can translate that to PHP:
SELECT p.id, p.message, o.subject
FROM
((SELECT t.id
FROM posts AS p LEFT JOIN topics AS t ON p.topic_id = t.id
GROUP BY t.id
HAVING p.posted = MAX(p.posted) ) ids LEFT JOIN topics AS t ON ids.id = t.id) o
LEFT JOIN posts AS p ON o.id = posts.topic_id
ORDER BY p.posted DESC
LIMIT '0,10'
change this line
'SELECT' => 'p.id, p.message, t.subject',
to
'SELECT DISTINCT' => 'p.id, p.message, t.subject',