I have a table named "likes" with this structure:
id - auto generated number,
bywho - user that likes someone ,
identifier - the liked user,
tip - the category of the like
i'm trying make a list with the most liked users(identifier), my problem is:
i need to generate the ammount of likes as a computed column in the list...
here is what i tried:
SELECT u.bywho,u.identifier COUNT(DISTINCT inv_by.identifier) AS lol
FROM likes u
LEFT JOIN likes inv_by ON u.identifier = inv_by.identifier
WHERE inv_by.identifier= $this->who AND tip='profil'
GROUP BY u.identifier ORDER BY lol DESC
I expect this isn't working because of the missing comma and grouping hasn't occured by u.bywho. The problem with doing that is it will give you a breakdown of the count by the person being liked and who liked them. Assuming a person can never be liked more than once, the count would always be one.
Try adding the comma after u.identiier in the select clause as mentioned by another reply.
If that doesn't work try grouping by u.who as well.
If that doesn't work as expected please explain what you expect a liitle more.
I'm guessing you may want to remove something from the select clause. Whatever non-aggregate is left in the select clause needs to be grouped upon.
Related
I am a newbie with sql queries so I have no clue how to create an accurate SQL.
I tried my best but I literally cannot find any similar example online, please help me out here.
The Data Schema as follows:
User(userID, username password, email, , userType)
Course(courseID, courseTitle)
Enroll(userID, courseID)
course rooms that users can access; note that users include all sorts of users such as teachers and administrators
Material(materialID, materialText, teacherUserID, courseID)
Question:
Find the two teachers who have access to most number of course rooms. Should there be a tie break, choose the ones with smaller user IDs. List the user ID, email, and the number of course rooms that s/he can access for the two teachers.**
The problems are:
SELECT userid, email, MIN (userid)
How can I specifically find the 2 smaller user IDs and which table should I select for finding out the course rooms? Do I have to use COUNT in this case?
FROM user JOIN enroll ON (user.usertype=enroll.userid)
As the enroll_table cannot identify whether the userID is teacher or administrator, if I use JOIN, can I find the the result that I want?
WHERE....
I don't know how to specifically find two teachers AND make sure they have tie break
Do I have to use GROUP BY and ORDER BY as well?
Just saw your attempted query. Look up how to format the code, so it stands out from the text. But you started about right. While we don't have the full info, try the following:
select user.userid,user.username, count(*) as cnt
from enroll
join user on user.userid=enroll.userid
where user.usertype="teacher"
group by user.userid
order by cnt DESC;
So Mary teaches three courses and comes out ahead. Since you want only the top two you can add the line LIMIT 2 to just get the two most prolific teachers.
The part that is hardest to understand for beginners is the group by clause, which generates aggregation, and which requires something like a count(*) clause in the first line. Read up on this separately and make yourself an even smaller example so you understand this well.
kenken068 also asked for a "tie break" using the userid so maybe the "order by" should be
order by cnt DESC, userid ASC;
Problem 1?
Limit to 2 based on the order on total. And also userid as tie braker.
Problem 2?
That info should be in User.userType
But then you need to know which userType is used for the teachers.
However, teachers have Material?
Problem 3?
See problem 1.
Problem 4?
Not always. But to calculate a total, a count is often used together with a group by.
SELECT
u.userID,
u.email,
COUNT(DISTINCT e.courseID) as TotalCourses
FROM `User` AS u
LEFT JOIN `Enroll` AS e
ON u.userID = e.userID
WHERE u.userID IN (SELECT DISTINCT teacherUserID FROM `Material`)
GROUP BY u.userID, u.email
ORDER BY TotalCourses DESC, u.userID
LIMIT 2
Select teacheruserID, count(courseID) from material
group by teacheruserID;
This will give you the count of courses the teachers have access to.
Then Simply order it in descending with the help of order by desc clause.
and the select TOP 2 with TOP Keyword
I am confused on this MySQL select query, I get the correct information back except the COUNT(messages) and COUNT(project_ideas) are coming back twice as many.
SELECT
create_project.title,
image1,
create_project.description,
create_project.date,
create_project.active,
create_project.completed,
create_project.project_id,
categories.name,
messages.receiver_read,
project_ideas.project_id,
COUNT(messages.ideas_id) AS num_of_messages,
COUNT(project_ideas.ideas_id) AS num_of_ideas
FROM
create_project
LEFT JOIN project_ideas ON create_project.project_id = project_ideas.project_id
LEFT JOIN messages ON messages.project_id = create_project.project_id
JOIN categories ON create_project.category = categories.category_id
WHERE
create_project.user_id = {$_SESSION['user']['user_id']}
AND create_project.active = 1
AND create_project.completed = 1
GROUP BY project_ideas.project_id
ORDER BY create_project.date ASC
Any help would be appreciated thanks.
If there is more than one row in your create_project table that matches to a single row in your messages table, then the row in messages will show up once for each matching row in create_project. Additionally, since you have many joins, you have many places for duplicate rows to show up. If a project belongs to more than one category, for example, your join against categories will result in every row from the other tables being duplicated for each category that a project belongs to. I'd wager this is actually the source of your error. And what makes it so insidious is that the GROUP BY hides the duplication everywhere except in functions that do counting and summing.
#Wrikken's comment is correct and useful. If you remove the GROUP BY, you'll see every row included in the count. There you should see that rows from the messages table are repeated. As #Wrikken also said, you can mitigate this by using COUNT(DISTINCT ...). I would try, however, to make sure your joins are correct or that your table data is correct, before papering over the problem with a COUNT(DISTINCT ...). That is to say, make sure that COUNT(DISTINCT ...) really makes logical sense in terms of the data you are looking for.
Unrelated to your action question, I had to point out something that I see (and have done myself before I knew better). Although MySQL lets you include columns in your select list that are not in a GROUP BY or an aggregate function (e.g., COUNT()), it's bad practice to do so. The results are technically undefined (see: http://dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html). I think MySQL is wrong for doing this, but it's not my call. Other database systems would flag this as an error.
Try this:
COUNT(messages.ideas_id) OVER(PARTITION BY messages.project_id) AS num_of_messages,
COUNT(project_ideas.ideas_id) OVER(PARTITION BY project_ideas.project_id) AS num_of_ideas
I have a database of Facebook Likes from several people. There are duplicate "like_id" fields across many "user_id"s. I want a query that will find the amount of "like_id"s person A has in common with person B.
This query is fantastic for comparing likes when only 2 "user_id"s are in the database, but as soon as I add a 3rd, it messes it up. Basically, I want to see who has the most "likes" in common with with person A.
SELECT *,
COUNT(*)
FROM likes
GROUP BY like_id
HAVING COUNT(*) > 1
Anyone have a query that might work?
This SQL should work. You just need to put in the User A's user_id and it should compare with all other users and show the top matching one. You can change it to show the top 5 or do whatever else you need to do.
Basically what it is doing is that it is doing a self join on the table, but making sure that when it does a join, it is a different user_id but the "like" is the same. Then it does a group by each of the other user_id's and sums the same amount of likes for that user_id.
SELECT all_other_likes.user_id, count(all_other_likes.like_id) AS num_similar_likes
FROM likes original_user_likes
JOIN likes all_other_likes
ON all_other_likes.user_id != original_user_likes.user_id
AND original_user_likes.like_id = all_other_likes.like_id
WHERE original_user_likes = USER_ID_YOU_WANT_TO_COMPARE
GROUP BY all_other_likes.user_id
ORDER BY count(all_other_likes.like_id) DESC
LIMIT 1;
Not sure what database you are using. You might need to do a SELECT TOP 1 if it is MS-SQL, but this is valid PostgreSQL and MySQL syntax.
I think this will do it:
SELECT
likes_a.user_id,
likes_b.user_id
FROM
likes as likes_a JOIN likes as likes_b
ON
likes_a.like_id = likes_b.like_id
WHERE
likes_a.user_id <> likes_b.user_id
And then post-process the results to count up who has the most in common.
I have a (what I am hoping to be easy) problem with a MySQL query.
I have 2 tables: articles, comments
An article can have many comments so there is a foreign of article_id in the comments table.
I want to get all the articles and while loop them to show on the page and then get all the comments count for each article. Easy, this is done. Now the problem is I want to sort the results based on number of comments but still show the results in the same way.
So basically I want to:
SELECT *
FROM tbl_articles
JOIN tbl_comments
ORDER BY (the most comments);
I am hoping this can all be done in a single query as the entire query is build dynamically from multiple sets of checkboxes where a single query could look like:
SELECT *
FROM tbl_articles
WHERE subject IN (1,2,5)
AND medium IN (1,3)
AND date_active > NOW()
AND...
Any further information I am happy to provide.
Something like...
SELECT *, COUNT(tbl_comments.id) as comments_count
FROM tbl_articles JOIN tbl_comments ON (tbl_comments.article_id = tbl_articles.id)
GROUP BY tbl_comments.article_id
ORDER BY comments_count;
I'm trying to create a single query which, similar to stack overflow, will give me the number of votes, but also make sure that the currently viewing user can't upvote again if they've already upvoted.
my query currently looks like
SELECT cid, text, COUNT(votes.parentid) FROM comments LEFT JOIN votes ON comments.cid=votes.parentid AND votes.type=3 WHERE comments.type=0 AND comments.parentid='$commentParentid' GROUP BY comments.cid
But I'm completely stumpted on how to add the check to see if the userid is in the votes table.
The other option is to add a seperate query where
SELECT COUNT(*) FROM votes WHERE userid='$userid' AND parentid='$commentParentid' AND type=3
I'm just realizing I'm so lost with this that I don't even really know what tags to provide.
SELECT cid, text, COUNT(votes.parentid),
COUNT(IF(votes.userid='$userid',1,NULL)) = 0 AS can_vote
FROM comments
LEFT JOIN votes ON comments.cid=votes.parentid AND votes.type=3
WHERE comments.type=0 AND comments.parentid='$commentParentid'
GROUP BY comments.cid
This should give you a flag can_vote based on the number of times the user has voted on the comment, if you insist on doing this in SQL.