I have an elementary question about SQL query with joining the same table twice. It sounds very simple, but I have some troubles with it. I hope, anyone can help me with this issue :)
I have two little tables: "peoples" (columns: id, name, ...) and "likes" (id, who, whom). People may set the "likes" to each other. The relationship is many to many.
I want get the table with peoples likes: count of received "likes", delivered and count of mutual likes.
All is correctly, when I use only one join. But for two joins (or more) MySQL combine all rows (as expected) and I get wrong values in counts. I don't know, how I must use count/sum/group-by operators in this case:( I would like to do this without subqueries in one query.
I used a query like this:
SELECT *, count(l1.whom), count(l2.whom)
FROM people p
LEFT JOIN likes l1 ON l1.who = p.id
LEFT JOIN likes l2 ON l2.whom = p.id
GROUP BY p.id;
SELECT p.id, name,
count(lwho.who) delivered_likes,
count(lwhom.whom) received_likes,
count(lmut.who) mutual_likes
FROM people AS p
LEFT JOIN likes AS lwho ON p.id = lwho.who
LEFT JOIN likes AS lwhom ON lwhom.id = lwho.id
LEFT JOIN likes AS lmut ON lwhom.who = lmut.whom AND lwhom.whom = lmut.who
GROUP BY p.id;
But it's calculated the counts of likes incorrect.
It's issue just for training and performance is not important, but I guess, that three joins in my last query is too much. Can I do it using 2 joins?
Thanks in advance for help.
I surmise that there is a 1:N relationship between people and likes.
One problem with your second query, as far as I can tell, is that the lwhom correlation of likes is joined to lwho via id=id. Basically lwhom is lwho. I'd recommend changing the ON clause for this correlation from lwhom.id = lwho.id to p.id = lwhom.whom.
The counts will still be affected by the JOINs, however. Supposing that you have an ID column in the likes table, though, you could then have each COUNT tally the distinct Like IDs per person – if not, consider just using COUNT(DISTINCT correlation.*) instead.
Digressions aside, the following should hopefully work:
SELECT p.id, name,
count(distinct lwho.id) delivered_likes,
count(distinct lwhom.id) received_likes,
count(distinct lmut.id) mutual_likes
FROM people AS p
LEFT JOIN likes AS lwho ON p.id = lwho.who
LEFT JOIN likes AS lwhom ON p.id = lwhom.whom
LEFT JOIN likes AS lmut ON lwhom.who = lmut.whom AND lwhom.whom = lmut.who
GROUP BY p.id,p.name;
I have an SQL Fiddle here.
Related
I'm trying to join 2 tables and count the number of entries for unique variables in one of the columns. In this case I'm trying to join 2 tables - patients and trials (patients has a FK to trials) and count the number of patients that show up in each trial. This is the code i have so far:
SELECT patients.trial_id, trials.title
FROM trials
JOIN(SELECT patients, COUNT(id) AS Num_Enrolled
FROM patients
GROUP BY trials) AS Trial_Name;
The Outcome I'm trying to acheive is:
Trial_Name Num_Patients
Bushtucker 5
Tribulations 7
I'm completely new to sql and have been struggling with the syntax compared to scripting languages.
It's not 100% clear from your question of the names of your columns however you are after a basic aggregation. Adjust the names of the columns if necessary:
select t.title Trial_Name, Count(*) Num_Patients
from Trials t
join Patients p on p.Trial_Id = t.Id
group by t.title;
Based on Stu-'s answer, I want to say that your column naming is wrong.But you can write query based on logic like this.
SELECT trial.title AS Trial_Name, COUNT(p.id) AS Num_Patients
FROM trial
INNER JOIN patients AS p
ON trial.patient_fk_id = p.id
GROUP BY trial.title,p.id;
Ugh... I really struggle with these mySQL joins...
Here's what I'm after. My current query looks like this.
SELECT profiles.photo, postings.postid, postings.text, postings.date, members.fname, members.lname, members.userid
FROM profiles, postings, members
WHERE postings.wallid=postings.posterid
AND postings.wallid=members.userid
AND postings.wallid=profiles.userid
I'm trying to add in a count(*) of matching records from another table. The other table is called likes, and postings.postid = likes.post_id.
What I've tried (and returns no results) is this...
SELECT profiles.photo, postings.postid, postings.text, postings.date, members.fname, members.lname, members.userid,
(SELECT COUNT(*) FROM likes WHERE postings.postid=likes.post_id)
FROM profiles, postings, members, likes
WHERE postings.wallid=postings.posterid
AND postings.wallid=members.userid
AND postings.wallid=profiles.userid
What I've done here is add the nested SELECT, which I thought would resolve this.
Basically, what I'm asking... given my first query, how can I also obtain the count of the number of records in the likes table where postings.postid = likes.post_id? As always, any help / tips / suggestions is always appreciated.
try that:
SELECT profiles.photo, postings.postid, postings.text, postings.date, members.fname,members.lname, members.userid,
likes.like_count
FROM profiles, members, postings
LEFT JOIN (SELECT post_id, COUNT(*) like_count FROM likes GROUP BY post_id) as likes
ON postings.postid=likes.post_id
WHERE postings.wallid=postings.posterid
AND postings.wallid=members.userid
AND postings.wallid=profiles.userid
First off, it's a lot easier to use the new-style sql syntax for this. Conceptually, it's going to be confusing and tough to do outer joins with that old syntax. Second, you're missing the "profile" table and mistakenly seem to have self-joined the postings table. Try writing your queries more like this:
SELECT
profiles.photo,
postings.postid,
postings.text,
postings.date,
members.fname,
members.lname,
members.userid,
COUNT(DISTINCT like_id) as CountOfLikes
FROM profiles
INNER JOIN postings
ON postings.wallid=profiles.userid
INNER JOIN members
ON members.userid=postings.wallid
LEFT JOIN likes
ON likes.post_id = postings.post_id;
I have a noob question but rather a troublesome one for me. I am using SELECT on three tables the middle one of which is realtional (Holds relations - ID of user against ID of Place), the first is a table of users, the last of places. I have written this perfectly woking query
$query = "SELECT users.Username,usrxplc.User,places.Name
FROM users,usrxplc,places
WHERE usrxplc.Place=places.ID AND usrxplc.User=users.ID"
That spits out all places associated with all users. Fine, but I would like to limit it only to a certain user. Seems simple, but I am stuck.
You use a WHERE clause to filter the results, so just add a clause for users.ID:
select users.Username,
usrxplc.User,
places.name
from users,
usrxplc,
places
where usrxplc.Place = places.ID
and usrxplc.User = users.ID
and users.ID = 123
Just felt the need to post the alternative - instead of selecting and all tables you can use INNER JOIN to join one table onto another
SELECT
users.Username,
places.Name
FROM users
INNER JOIN usrxplc ON usrxplc.User=users.ID
INNER JOIN places ON places.ID = usrxplc.Place
WHERE users.ID = 111
It's functionally the same as the other answer, however when you get onto more complex queries and tables you will find that using JOINs allows for greater optimisation as you are able to further limit the rows each individual JOIN gets, for example the following is also valid, where the User row is limited before joining onto other tables
SELECT
users.Username,
places.Name
FROM places
INNER JOIN usrxplc ON usrxplc.Place = places.ID
INNER JOIN users ON users.ID = usrxplc.User AND users.ID = 111
In more complicated queries, or if these tables were to be far larger, this would in turn offer a more optimal query generally speaking
I have three tables that I need get information from, 1 table has the information in and the other two hold information that i need to count.
so the first tables structure is:
tbl_img
img_id
img_name
tbl_comments
comment_id
img_id
comment
tbl_vote
vote_id
logo_id
I want the results to have the count of comments and votes that relate to each logo.
I have a bit of the query which is for the count of comments, but have no idea for the syntax for the second join.
SELECT l.img_id, l.img_name, COUNT(c.comment_id) AS comment_count
FROM tbl_images as l
LEFT OUTER JOIN tbl_comments AS c USING (img_id);
Can anyone help?
how about this :
SELECT l.img_id, l.img_name,
(SELECT COUNT(*) FROM tbl_comments c WHERE i.img_id = c.img_id ) AS comment_count,
(SELECT COUNT(*) FROM tbl_vote v WHERE i.img_id = v.img_id ) AS vote_count
FROM tbl_images i
Sounds like you need two queries for this: One for counting the votes, and one for counting the comments.
As far as I know, COUNT counts result rows, and joins create result rows to display all allowed permutations of joined tables.
Assuming you have I entries, each with J comments and K votes, you would receive J*K rows for each entry after joins, and COUNTs would both return that J*K instead of the correct amount.
I do not remember if you can do inner queries in MySQL, but that would be the way to go.
(See #Kevin Burtons answer)
I'm having a problem with my MySQL statement. I need a query that counts the number of comments and the number of topics a user has created. My table structure is something like this:
Table 'users'
-------------
user_id
user_name
...
Table 'topics'
--------------
topic_id
topic_user_id
...
Table 'topiccomments'
---------------------
topiccomment_id
topiccomment_user_id
...
So far I've been able to produce this query:
SELECT
u.user_id,
u.user_name,
COUNT(t.topic_user_id) as topic_count,
COUNT(tc.topiccomment_user_id) as topiccomment_count
FROM
users as u
JOIN topiccomments as tc ON u.user_id = tc.topiccomment_user_id
JOIN topics as t ON u.user_id = t.topic_user_id
WHERE
u.user_id = t.topic_user_id AND
u.user_id = tc.topiccomment_user_id
GROUP BY
u.user_id
This query is executed, but the 'topic_count' and 'topiccomment_count' values are totally wrong and I don't quite understand why.
I was hoping somebody here could help me out?
change to
COUNT(DISTINCT t.topic_id) as topic_count,
COUNT(DISTINCT tc.topiccomment_id) as topiccomment_count
This will count the number of distinct topics and topic comments that match the user ID. Before, you were counting the number of rows in the cross-product of topics and topic comments for a given user.
If it works in your situation, I would refactor this into two queries, one for counting topics and one for topic_comments, since this will be more efficient.
quick shot: try replacing count(field) with count(distinct field)
First of all, you can delete your entire WHERE clause. It is not necessary because you already took care of it in the JOINs.
To fix your issue, use this in your SELECT clause instead of the current COUNT statements your have:
COUNT(DISTINCT t.topic_id) as topic_count,
COUNT(DISTINCT tc.topiccomment_id) as topiccomment_count
You are trying to count the number of topics, or topic comments. Not the number of users (which should always be 1).
The JOINs are probably returning a cartesian product of the topiccomments and topics tables because there is no restriction between their relationship, which could explain why you are getting a high count.
One easy way to tackle this problem is to use correlated subqueries:
SELECT u.user_id,
u.user_name,
SELECT (COUNT(*) FROM topics t WHERE t.id = u.id),
SELECT (COUNT(*) FROM topiccomments tc WHERE tc.id = u.id)
FROM users u;
You can also use COUNT(DISTINCT t.topic_id) and COUNT(DISTINCT tc.topiccomment_id) in your original query as some of the other answers suggest. In fact, that may turn out to be more efficient in terms of performance.
You should be counting the topic and comment ids, not the user_ids of the comment/topic.
SELECT
u.user_id,
u.user_name,
COUNT(DISTINCT t.topic_id) as topic_count,
COUNT(DISTINCT tc.topiccomment_id) as topiccomment_count
FROM
users as u
JOIN topiccomments as tc ON u.user_id = tc.topiccomment_user_id
JOIN topics as t ON u.user_id = t.topic_user_id
GROUP BY
u.user_id