How to query multiple tables using different constraints?
For example, limiting results to 1 row from the first table, but getting all results from the second and then ordering those results by unique id ASC.
For example, something like this:
SELECT p.entry_id AS post_id,
p.topic AS post_topic,
p.body AS post_body,
r.reply AS post_reply
FROM
#should get only one row
(SELECT entry_id, topic, body FROM entry_posts WHERE entry_id = {$id} LIMIT 1) AS p
FULL JOIN
#should get all rows with this entry_id and order them
(SELECT reply, FROM entry_replies WHERE entry_id = {$id} ORDER BY id ASC) AS r
ON p.entry_id = r.entry_id
In this case both tables have a column called entry_id that contain the same values.
SELECT p.entry_id AS post_id,
p.topic AS post_topic,
p.body AS post_body,
r.reply AS post_reply
FROM entry_posts p
LEFT OUTER JOIN entry_replies r ON r.entry_id = p.entry_id
WHERE p.entry_id = {$id}
ORDER BY r.id
Related
Okay so I have three(3) tables that i want to join together
tableA is the main details and primary key is row_id autoincremented
tableB is the exteded details and primary/foreign key is row_id coming from tableA
tableC stores unordered ratings and comments for a particular row_id
I want to join all these tables so that I can see all details plus the number of instances in tableC for a row_id and the avg rating.
SELECT *
FROM `tableA` A
LEFT JOIN `tableB` B
ON A.`row_id` = B.`row_id`
LEFT JOIN (
SELECT COUNT( 1 ) AS 'count', Avg(`row_rating`) AS 'avg'
FROM `tableC`
GROUP BY tableC.`row_id`
)C
ON C.`row_id` = A.`row_id`
ORDER BY C.`avg` ASC
The result of this query combines all properly but the same count and avg is displayed in all rows.
Looks like you want to group the records by row_id in inner query. In which case, you need to SELECT row_id instead of COUNT(1), try this:
SELECT *
FROM `tableA` A
LEFT JOIN `tableB` B
ON A.`row_id` = B.`row_id`
LEFT JOIN (
SELECT row_id, Avg(`row_rating`) AS 'avg'
FROM `tableC`
GROUP BY tableC.`row_id`
)C
ON C.`row_id` = A.`row_id`
ORDER BY C.`avg` ASC
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 a query where I want to fetch columns from two tables (a parent and reference table), as well as select total number of categories of each post on the reference table
articles
id
title
poster
pdate
content
categories
id
name
cats_rel (Relationship table with Foreign Key constraints)
id
pid
cat_id
I want to fetch list of posts with one category id and total number of categories for each post.
I use this to fetch the required data, but it is slow. Is there a better way to get it faster?
SELECT cc.id, title, poster, pdate, content, js.pid, js.sno
FROM articles cc LEFT JOIN
(SELECT pid, cat_id, count(cat_id) as sno FROM cats_rel GROUP BY pid)js
ON js.pid = cc.id WHERE cc.status='approved' ORDER BY cc.id DESC
You don't need a inner query.
SELECT cc.id, title, poster, pdate, content, js.pid, count(js.cat_id) as sno
FROM articles wp
LEFT JOIN cats_rel js ON js.pid = cc.id
WHERE wp.status='approved'
group by cc.id, title, poster, pdate, content, js.pid
ORDER BY cc.id DESC
I would rewrite the query using a correlated subquery
SELECT cc.id, cc.title, cc.poster, cc.pdate, cc.content,
(SELECT COUNT(*)
FROM cats_rel js
WHERE js.pid = cc.id
) as sno
FROM articles cc
WHERE cc.status = 'approved'
ORDER BY cc.id DESC;
(It seems that js.pid is redundant in the select list.)
For this query, you want two indexes: articles(status, id desc) and cats_rel(pid).
I have two tables,
TABLE 1 has many of each client and campaign and is very large
TABLE 2 has only one of each client and campaign and is small.
So I want to get the lastest(highest ID) from TABLE 1 where it matches the client and campaign in TABLE 2 and only one of each.
I have tried MAX, and playing with the order by etc, but cant get it working....
The results I get are choosing the lowest ID from TABLE 1 (I want highest)
$result2 = mysql_query("SELECT table1.client,table1.campaign,table1.id
FROM table1
LEFT OUTER JOIN
table2
ON (table2.client = table1.client)
AND (table2.campaign = table1.campaign )
WHERE (table2.enabled != 'disabled')
group by campaign asc
order by client,campaign,id asc
");
Help needed....
SELECT * FROM table1
INNER JOIN
(
SELECT MAX(table1.id) AS id FROM table1
INNER JOIN table2 ON table2.client = table1.client AND table2.campaign=table1.campaign and table2.enabled != 'disabled'
GROUP BY table1.client, table1.campaign
) AS m ON m.id = table1.id
I think that's what you're asking for. For each combination of client and campaign that exists in each table, it will give you the highest ID in table 1.
I have a table categories and table posts . I want to return categories that have more than 3 posts.
My query
SELECT `categories`.`category_title`, COUNT(posts.post_id) as total_posts
FROM (`categories`)
JOIN `posts` ON `posts`.`category_id` = `categories`.`category_id`
HAVING `total_posts` > 3
ORDER BY `categories`.`date_created` desc
it returns just 1 row.. What is the correct way to do this type of query without using 2 queries?
Your query is making use of a MySQL feature called "hidden columns" and you might not even know it. This is because your query is referencing elements, such as date_created, which should be aggregated but are not ("should" here means according to the SQL standard and most other databases).
The problem with your query is that it is missing the group by. An alternative way of writing this is with the aggregation in a subquery, before joining to category:
SELECT `categories`.`category_title`, total_posts
FROM `categories` JOIN
(select categoryid, COUNT(posts.post_id) as total_posts
from `posts`
group by categoryid
having count(*) > 3
) pc
ON `pc`.`category_id` = `categories`.`category_id`
ORDER BY `categories`.`date_created` desc
You need to group the items by category.
SELECT `categories`.`category_title`, COUNT(posts.post_id) as total_posts
FROM (`categories`)
JOIN `posts` ON `posts`.`category_id` = `categories`.`category_id`
GROUP BY `categories`.`category_id`
HAVING `total_posts` > 3
ORDER BY `categories`.`date_created` desc