I have 2 tables conversation and participants, I would like to get the list of conversations and participants in each of them. Can I do that in only one query or I have to do 2 queries one for conversation and the second for getting participants for each conversation ?
I tried with
SELECT c.*, (SELECT p.user FROM participants p WHERE p.conversation_id = c.id ) AS participants
FROM `conversation` c
ORDER BY c.date DESC
But i get "error 1242 subquery returns more than 1 rows" and that's normal !
Use an INNER JOIN to select parts of different tables where a common ID is shared. Like this:
SELECT c.*, p.user
FROM conversation AS c INNER JOIN participants AS p ON p.conversation_id = c.id
ORDER BY c.date DESC
Right now you are using a subquery
(SELECT p.user FROM participants p WHERE p.conversation_id = c.id )
to receive a new column, in the table you are creating. A column only has one value for every row, not multiple values. So an error is thrown in this case. If you are confident that you will not miss data then you could force your subquery to return one each time it is run with aggregates
(SELECT max(p.user) FROM participants p WHERE p.conversation_id = c.id )
But if the multiple values are different and still important, which in most cases is likely you want to do the join as mentioned by my friend Erik.
A join is likely what you are looking for.
SELECT c.*, p.user
FROM conversation c
inner join
Participants p
on p.conversation_id = c.id
ORDER BY c.date DESC
Related
I have a table of ratings for comments, when I fetch comments, I also fetch the ratings and I also want to be able to display which comments the logged user has already voted on. This is what I am doing now
SELECT
c.id,
c.text,
c.datetime,
c.author,
u.email AS author_name,
SUM(cr.vote) AS rating,
cr2.vote AS voted
FROM comments c
LEFT JOIN users u ON u.id = c.author
LEFT JOIN comments_ratings cr ON c.id = cr.comment
LEFT JOIN comments_ratings cr2 ON c.id = cr2.comment AND cr2.user = :logged_user_id
GROUP BY c.id ORDER BY c.id DESC
But I don't like how I'm performing a second join on the same table. I know it is perfectly valid but if I could get the information I want from the first join, which is there anyway, why perform a second one?
Is it possible to figure out if a row with column user equal to :logged_user_id exists on table comments_ratings cr before executing the aggregate function(s)?
P.S.: If someone could come up with a better title, people can find in future, I'd also appreciate that.
You can do what you want with conditional aggregation:
SELECT c.id, c.text, c.datetime, c.author, u.email AS author_name,
SUM(cr.vote) AS rating,
MAX(cr.user = :logged_user_id) as voted
FROM comments c LEFT JOIN
users u
ON u.id = c.author LEFT JOIN
comments_ratings cr
ON c.id = cr.comment
GROUP BY c.id
ORDER BY c.id DESC;
I'm currently retrieving data from 3 different tables. One of those tables contain messages sent which relates to each ID.
What I'm currently trying to do but have been unsuccessful is retrieve the last message on record for each ID.
Help please-
select
C.id ,
C.business,
AP.firstname,
AP.lastname,
M.comments,
M.dateread
from
claims C
JOIN
affected_people AP
ON C.ID = AP.claimid
join
Messages M
on M.claimid = C.ID
Not sure, if that works for mysql:
select *
from(
select
C.id ,
C.business,
AP.firstname,
AP.lastname,
M.comments,
M.dateread,
max(M.dateread) over (partition by c.id) max_dateread
from
claims C
JOIN
affected_people AP
ON C.ID = AP.claimid
join
Messages M
on M.claimid = C.ID)
where max_dateread=dateread
Just add in
Order by M.dateread desc
I have 3 tables: activites, taks and requirements. I want to return all of the duration of all the tasks for a specific requirement. This is my query:
SELECT r.id as req_id,
r.project_id,
r.name as req_name,
r.cost,r.estimated,
p.name as project_name,
v.name AS `status` ,
t.taskid,
(SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(duration)))
FROM activities a
WHERE a.taskid = t.taskid) AS worked
FROM requirements r
INNER JOIN projects p
ON p.projectid = r.project_id
INNER JOIN `values` v
ON v.id = r.r_status_id
LEFT JOIN tasks t
on t.id_requirement = r.id
WHERE 1 = 1
ORDER BY req_id desc
And this is the result :
As you can see there are 2 same req_id (48) . I want to appear one time and get the sum of the last two rows in worked. How can I manage that ?
this is the activities structure :
this is tasks structure :
and this is the requirement structure :
Include your activities table in the JOIN, GROUP by all requirement columns you need and add a sum. Since you are aggregating tasks, you cannot have taskid in the SELECT clause.
SELECT r.id as req_id,
r.project_id,
r.name as req_name,
r.cost,r.estimated,
p.name as project_name,
v.name AS `status` ,
SEC_TO_TIME(SUM(TIME_TO_SEC(a.duration)))
FROM requirements r
INNER JOIN projects p ON p.projectid = r.project_id
INNER JOIN `values` v ON v.id = r.r_status_id
LEFT JOIN tasks t ON t.id_requirement = r.id
LEFT JOIN activities a ON a.taskid=t.taskid
WHERE 1 = 1
GROUP BY r.id, r.project_id, r.name,r.cost,r.estimated,p.name, v.name
ORDER BY req_id desc
The joins in your query appear to be creating extra rows. I'm sure there is a way to fix the logic directly, possibly by pre-aggregating some results in the from clause.
Your duplicates appear to be complete duplicates (every column is exactly the same). The easy way to fix the problem is to use select distinct. So, just start your query with:
SELECT DISTINCT r.id as req_id, r.project_id, r.name as req_name,
. . .
I suspect that one of your underlying tables has duplicated rows that you are not expecting, but that is another issue.
Basically I'm just unsure as to why this query is failing to execute:
(SELECT replies.reply_post, replies.reply_content, replies.reply_date AS d, members.username
FROM (replies) AS a
INNER JOIN members ON replies.reply_by = members.id)
UNION
(SELECT posts.post_id, posts.post_title, posts.post_date AS d, members.username
FROM (posts) as b
WHERE posts.post_set = 0
INNER JOIN members ON posts.post_by = members.id)
ORDER BY d DESC LIMIT 5
I'm getting this error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'a INNER JOIN members ON replies.re' at line 2
All I'm trying to do is select the 5 most recent rows (dates) from these two tables. I've tried Join, union etc and I've seen numerous queries where people have put another query after the FROM statement and that just makes no logical sense to me as to how that works?
Am I safe to say that you can join the same table from two different but joined queries? Or am I taking completely the wrong approach, because frankly I can't seem see how this query is failing despite reading the error message.
(The two queries on there own work fine)
I think there is syntax error in your query at below part :
FROM (posts) as b
WHERE posts.post_set = 0
INNER JOIN members ON posts.post_by = members.id)
Inner join should come first before where condition. Also your join conditions are wrong. You need to apply conditions like
INNER JOIN members ON a.reply_by = members.id)
INNER JOIN members ON b.post_by = members.id)
So your query should be like this
(SELECT a.reply_post, a.reply_content, a.reply_date AS d, members.username
FROM (replies) AS a
INNER JOIN members ON a.reply_by = members.id)
UNION
(SELECT b.post_id, b.post_title, b.post_date AS d, members.username
FROM (posts) as b
INNER JOIN members ON b.post_by = members.id
WHERE b.post_set = 0)
ORDER BY d DESC LIMIT 5
Try this:
(SELECT a.reply_post, a.reply_content, a.reply_date AS d, members.username
FROM replies AS a
INNER JOIN members ON a.reply_by = members.id)
UNION
(SELECT b.post_id, b.post_title, b.post_date AS d, members.username
FROM posts as b
INNER JOIN members ON b.post_by = members.id
WHERE b.post_set = 0) /* Use where condition after matching Id's using ON */
ORDER BY d DESC LIMIT 5
I have a query to pull a total number for a given publisher ID. I'd like to use it as a subquery so I can iterate over all publisher IDs.
My working query for a given ID is:
SELECT SUM( d.our_cost )
FROM articles a
CROSS JOIN domains d ON a.domain_id = d.id
AND d.publisher_id = '1094'
I'd like to pull this figure for all ID's in publisher p table where d.publisher_id = p.id
So far I've tried the following to no avail:
SELECT p.id, p.contact_name, p.contact_email,
(SELECT SUM(d.our_cost)
FROM articles a
CROSS JOIN domains d ON a.domain_id = d.id and d.publisher_id = p.id) total
FROM publishers p
The specific error I'm getting is: Unknown column 'p.id' in 'on clause'
I think you should modify your query and put the subquery in the from clause, something like this:
SELECT p.id, p.contact_name, p.contact_email, total.total_cost
FROM
(
SELECT SUM(d.our_cost) as total_cost, d.publisher_id
FROM articles a CROSS JOIN domains d ON a.domain_id = d.id ) total
JOIN publishers p on total.publisher_id = p.id
I'm assuming you've gotten an error about your syntax, try:
SELECT p.id, p.contact_name, p.contact_email, SUM(d.our_cost) as total
FROM articles a
CROSS JOIN domains d ON a.domain_id = d.id
JOIN publishers p ON d.publisher_id = p.id
seems like a group by would be handy here instead
Also it seems like you dont need articles table at all (unless you have additional business rules)
SELECT p.id, p.contact_name, p.contact_email, IFNULL(SUM(d.our_cost),0) AS total
FROM publishers p
LEFT JOIN domains d ON d.publisher_id = p.id
GROUP BY p.id