I have two tables:
news ->
id_news
title
body
date_created
image
category_id
comments ->
id_comments
news_id
body
date_created
How can I write query to get all news, count all the comments for every news and present that query in the view part?
select
N.ID_News,
N.Title,
N.Body,
N.Date_Created,
N.Image,
N.Category_ID,
count(C.ID_Comments) CommentCount
from
News N
LEFT JOIN Comments C
on N.ID_News = C.News_ID
group by
N.ID_News
order by
whatever column(s) are important to you
Since we are counting, we need to make a minor change to DRap's Query:
select
N.ID_News,
N.Title,
N.Body,
N.Date_Created,
N.Image,
N.Category_ID,
count(C.ID_Comments) CommentCount
from
News N
LEFT JOIN Comments C
on N.ID_News = C.News_ID
order by
whatever column(s) are important to you
That will only give you only one result.. as that query lacks a group by statement, I would recommend changing that query to this:
select
N.ID_News,
N.Title,
N.Body,
N.Date_Created,
N.Image,
N.Category_ID,
count(C.ID_Comments) CommentCount
from
News N
LEFT JOIN Comments C
on N.ID_News = C.News_ID
group by
N.title
order by
whatever column(s) are important to you
Writing this down in the Active Record format stays something like this:
$this->db->select('N.ID_News, N.Title, N.Body, N.Date_Created, N.Image')
$this->db->select('N.Category_ID, count(C.ID_Comments) AS CommentCount');
$this->db->from('News AS N');
$this->db->join('commentas AS C', 'N.ID_News = C.News_ID', 'left');
$this->db->group_by('N.title');
After this you can use the order by funtion, to order the resultsas you seefit.
Related
I am trying to make an sql search query to return only ORDERS that match my search keyword. The issue is that i also need to search in every comments body for each order and if a result is found in that comment the order for that comment should be selected. The tables looks like this in a simplified way:
ORDERS:
ID = 95
title = first order
COMMENT RELATIONS:
id = 1241
comment_id = 500
target_id = 95
type = order
COMMENTS:
id = 500
body = this is the first comment
So if i searched for "first comment" the order with id 95 should be selected.
My current attempt seems to select more then order but also their comments and relations? This is how my current attempt looks like.
$query = 'SELECT DISTINCT *
FROM orders as o
LEFT JOIN comment_relations as cr ON o.id = target_id
LEFT JOIN comments as c ON cr.comment_id = c.id
WHERE o.id LIKE :keyword OR o.title LIKE :keyword OR c.body LIKE :keyword';
Not sure which database you are using but in most databases you can use the table alias follow by * for selecting only one table.
'SELECT DISTINCT o.*
FROM orders as o
LEFT OUTER JOIN comment_relations as cr ON o.id = target_id
LEFT OUTER JOIN comments as c ON cr.comment_id = c.id
WHERE o.id LIKE :keyword OR o.title LIKE :keyword OR c.body LIKE :keyword';
As per your concept i create 3 demo tables in phpmyadmin which description is here.
1.orders have columns (id,title).
2.comment_relations have columns (id,comment_id,target_id,type).
3.comments have columns (id,body).
This is SQL Query for fetch records from order by match keyword from comments table.
select DISTINCT o.* from orders o LEFT JOIN comment_relations cr ON o.id=cr.target_id LEFT JOIN comments c ON c.id=cr.comment_id where body LIKE '%keyword%'
On applying this query by replace your keyword at place of keyword you get this result.
Here i match keyword "first comment"
I have an articles table that and I am displaying it in the homepage in a while loop. Inside the while loop I want to display the comments count and images count for each article.
It is working for me now, but it is three queries in total, I am trying to combine it in the first query and then just display all of them in one while loop. Here is what I am trying to achieve:Articles page
The current format I am following:
//a represents articles table, c represents comments table, i represents image table
$query = mysqli_query($conn, "SELECT a.a_id, a.title, a.datetime, a.user_id FROM a ORDER BY a.datetime DESC");
while($fetch = mysqli_fetch_assoc($query){
$imageQ = msqli_query($conn, "SELECT COUNT(image_path), image_path FROM i WHERE a_id = '$fetch['a_id']'");
$imageFetch = mysqli_fetch_assoc($imageQ);
$commentQ = mysqli_query($conn, "SELECT COUNT(comment_id) FROM c WHERE a_id = '$fetch['a_id']'");
$commentFetch = mysqli_fetch_assoc($commentQ);
}
I want to cram all of these queries into one single query that fetches the article and comments count and image count for each article and the first image.
The images and comments are separate dimensions of the data. So, you have to be careful about how to bring them together. In your case, you can aggregate the values before doing the joins:
SELECT a.a_id, a.title, a.datetime, a.user_id,
i.num_images, c.num_comments
FROM a LEFT JOIN
(SELECT a_id, COUNT(image_path) as num_images
FROM i
GROUP BY a_id
) i
ON i.a_id = a.a_id LEFT JOIN
(SELECT a_id, COUNT(comment_id) as num_comments
FROM c
GROUP BY a_id
) c
ON c.a_id = a.a_id
ORDER BY a.datetime DESC;
You can use mysql nested queries something like
SELECT a.,tab1.,tab2.* FROM a INNER JOIN (SELECT * FROM b ) as tab1 INNER JOIN (SELECT * FROM c) as tab2
Hope this can get you to get desired output.
Thanks
I have 3 tables: 'news', 'comments' and 'rub'. I need to get all data from 'news', get 'title' from 'rub' and count the number of comments for every news.
Now I'm not able to get 'title' from 'rub'. The code below works:
SELECT n.id,n.header,n.text, COUNT(c.news_id) AS comments
FROM news n
LEFT JOIN comments c ON n.id = c.news_id
GROUP BY n.id
ORDER by n.id
LIMIT 30
But I need something like that and this code doesn't work (Call to a member function fetch_array() on a non-object):
SELECT n.id,n.header,n.text,r.title COUNT(c.news_id) AS comments
FROM news n,rub r
LEFT JOIN comments c ON n.id = c.new_id AND r.news_id=n.id
GROUP BY n.id ORDER by n.id
LIMIT 30
How to fix it?
It's not really clear to me what you are asking, but you need another JOIN. And you need to move the join condition for the rub table to that JOIN keyword, not into the join condition for the comments table
SELECT n.id,
n.header,
n.text,
r.title, -- comma was missing (as halfer mentioned)
COUNT(c.news_id) AS comments
FROM news n
JOIN rub r ON r.news_id=n.id --- this is missing
LEFT JOIN comments c ON n.id = c.new_id -- no join condition for rub/news here
GROUP BY n.id
ORDER by n.id
LIMIT 30
Your usage of the GROUP BY operator is also wrong. The above query will (rightfully) be rejected by all other DBMS.
Please read the following to understand why your GROUP BY is wrong:
http://www.mysqlperformanceblog.com/2006/09/06/wrong-group-by-makes-your-queries-fragile/
http://rpbouman.blogspot.de/2007/05/debunking-group-by-myths.html
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
This is relating to my last question mysql query with AND, OR and NOT
Instead of editing the question, I am asking a new one because the question is only part of the previous question with an alteration.
I am looking to do a mysql query that returns me all articles that have all required topics.
Article
id
....
Topic
id
....
ArticleTopics
article_id
topic_id
type
something that would effectively do:
SELECT * FROM Article LEFT JOIN ArticleTopics ON Article.id = ArticleTopics.article_id
WHERE ArticleTopics.topic_id HAS ALL (these topics)
Is this possible? What is the best approach for this?
Several of the other answers suggest using aliases on the child table for each filter clause - this may not be very efficient or scale well.
Consider:
SELECT x.*
FROM Article x INNER JOIN
(SELECT t.article_id, COUNT(t.article_id)
FROM articleTopics t
WHERE t.topic_id IN ([your_list_of_topics])
GROUP BY t.article_id
HAVING COUNT(t.article_id)>=[number of elements in [your_list_of_topics]]
ORDER BY COUNT(t.article_id) DESC
LIMIT 0,100) AS ilv
ON x.id=ilv.article_id
Another advantage of this approach is that the structure of the query doesn't need to change with the number of topics you are searching for - you could even put them in a temporary table and perform a join instead of using the ' IN (...)' literal.
You'd need to try it out to see which query behaves better.
That is done using multiple joins with the same table.
To select all articles that have topics with ID 1, 2 and 3, you need to do:
SELECT * FROM Article a
INNER JOIN ArticleTopics at1 ON a.id = at1.article_id AND at1.topic_id = 1
INNER JOIN ArticleTopics at2 ON a.id = at2.article_id AND at2.topic_id = 2
INNER JOIN ArticleTopics at3 ON a.id = at3.article_id AND at3.topic_id = 3
// EDIT
Fixed it. Added table aliasses; I must have been working with good ORM solutions for too long...
SELECT
*
FROM
Article
WHERE
(SELECT COUNT(*) FROM ArticleTopics
WHERE Article.id = ArticleTopics.article_id AND
ArticleTopics.topic_id=1) > 0 AND
(SELECT COUNT(*) FROM ArticleTopics
WHERE Article.id = ArticleTopics.article_id AND
ArticleTopics.topic_id=2) > 0 AND
(SELECT COUNT(*) FROM ArticleTopics
WHERE Article.id = ArticleTopics.article_id AND
ArticleTopics.topic_id=3) > 0 AND
...