Compound query solutions based on no.of rows - mysql

I have three table
td_idea
|------------|-------------|
| idea_id | idea_name |
|------------|-------------|
then td_idea_comment
|-----------|------------|----------
|comm_id | idea_id | user_id |
|-----------|------------|----------|
and td_idea_like
|-----------|------------|----------
|comm_id | idea_id | user_id |
|-----------|------------|----------|
Now I need to use a query which will order the idea in ascending order based on the no. of votes in td_idea_like and no. of comments on td_idea_comment.
A example to the three tables is as follows
td_idea
|------------|-------------|
| idea_id | idea_name |
|------------|-------------|
| 1 | Pink Ruby |
|------------|-------------|
| 2 | Black_ruby |
|------------|-------------|
td_idea_comment
|------------|-------------|---------------|
| comm_id | idea_id | user_id |
|------------|-------------|---------------|
| 1 | 1 | 1 |
|------------|-------------|---------------|
| 2 | 2 | 1 |
|------------|-------------|---------------|
| 3 | 1 | 2 |
|------------|-------------|---------------|
| 4 | 1 | 3 |
|------------|-------------|---------------|
td_idea_like
|------------|-------------|---------------|
| like_id | idea_id | user_id |
|------------|-------------|---------------|
| 1 | 1 | 1 |
|------------|-------------|---------------|
| 2 | 2 | 1 |
|------------|-------------|---------------|
| 3 | 1 | 2 |
|------------|-------------|---------------|
| 4 | 1 | 3 |
|------------|-------------|---------------|
I used this query
SELECT * FROM td_idea,td_idea_comment,tyd_idea_like
WHERE td_idea.idea_id=td_idea_comment.idea_id
AND td_idea.idea_id=td_idea_like.idea_id
Order BY (SELECT COUNT(*) AS tot_comment FROM td_idea,td_idea_comment
WHERE td_idea.idea_id=td_idea_comment.idea_id),
(SELECT COUNT(*) AS tot_like FROM td_idea,td_idea_like
WHERE td_idea.idea_id=td_idea_like.idea_id)
but it returns me zero if in any case either there is no row in td_idea_comment based on a particular idea or no row in td_idea_like based on a particular idea.
Say:
idea id 1 has 3 likes 3 comments
idea id 2 has 1 likes 2 comments
idea id 3 has 0 likes 4 comments
then for idea id 3, the resultant is returned as 0.
While I want it to be sorted as this
idea id 1(since 3+3)
idea id 3(since 0+4)
idea id 2(since 1+2)

SELECT a.idea_id,
a.idea_name,
COUNT(DISTINCT b.like_ID) totalLikes,
COUNT(DISTINCT c.comm_ID) totalComment
FROM td_idea a
LEFT JOIN td_idea_like b
ON a.idea_ID = b.idea_ID
LEFT JOIN td_idea_comment c
ON a.idea_ID = c.idea_ID
GROUP BY a.idea_id, a.idea_name
ORDER BY COUNT(DISTINCT b.like_ID) + COUNT(DISTINCT c.comm_ID) DESC
SQLFiddle Demo
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins

Related

mysql table ordering incorrect with group by and order by

table 1: forum_threads
+-----+------+-------+
| id | title| status|
+-----+------+-------+
| 1 | a | 1 |
| 2 | b | 1 |
| 3 | c | 1 |
| 4 | d | 1 |
| 5 | e | 1 |
| 6 | f | 1 |
+-----+------+-------+
table 2: forum_comments
+-----+----------+--------------------+
| id | thread_id| comment |
+-----+----------+--------------------+
| 1 | 4 | hai |
| 2 | 4 | hello |
| 3 | 2 | welcome |
| 4 | 2 | whats your name |
| 5 | 6 | how are you |
| 6 | 5 | how old are you |
| 7 | 5 | good |
+-----+----------+--------------------+
wanted output
+-----------+----------+-----------------+
| thread_id | title | comment_count |
+-----------+----------+-----------------+
| 5 | e | 2 |
| 6 | f | 1 |
| 2 | b | 2 |
| 4 | d | 2 |
+-----------+----------+-----------------+
my Query
SELECT forum_threads.*,forum_comments.*,count(forum_comments.id) as comment_count
FROM forum_comments
LEFT JOIN forum_threads ON forum_comments.thread_id = forum_threads.id
GROUP BY forum_threads.id
ORDER BY forum_comments.id desc
Here I am trying to get the titles by the latest comment.
when I give ORDER BY forum_comments.id this returns the wrong order.
I need to order by the latest comments in the forum_comments table.
this query returns the wrong order please help me to find out the correct order.
how could I solve this easily?
This query should give you the expected result:
select t2.thread_id, t1.title, t2.comment_count from forum_threads as t1,
(SELECT id, thread_id, count(comment) as comment_count from forum_comments group by thread_id) as t2
where t1.id = t2.thread_id order by t2.id desc;
Instead of using forum_threads.* and forum_comments.* can you give specific column names and try.
If that doesn't work you should try explicitly assigning primary and foreign keys.

How can I get a total count of items?

I'm trying to figure out a MYSQL string and my noob-ness is getting in my way. I'm trying to count the total number of teams per phase.
Tables to consider:
phases
+----+------------+
| id | phase_name |
+----+------------+
| 1 | start |
| 2 | middle |
| 3 | end |
| 4 | finish |
+----+------------+
teams
+----+-----------+----------+
| id | team_name | phase_id |
+----+-----------+----------+
| 1 | team1 | 2 |
| 2 | team2 | 3 |
| 3 | team3 | 3 |
| 4 | team4 | 4 |
| 4 | team5 | 3 |
+----+-----------+----------+
Desired result
+----------+------------+-----------+
| phase_id | phase_name | tot_teams |
+----------+------------+-----------+
| 1 | start | NULL |
| 2 | middle | 1 |
| 3 | end | 3 |
| 4 | finish | 1 |
+----------+------------+-----------+
I've tried:
SELECT
T.phase_id, P.phase_name, COUNT(*) AS tot_teams
FROM
teams T
LEFT JOIN
phases P ON P.id = T.phase_id
GROUP BY
phase_id;
but that only shows the affected phase_id's...and I'm hoping to get ALL phase_id's in a table. I also tried:
SELECT
P.phase_name, T.phase_id, COUNT(*)
FROM
teams T
RIGHT JOIN
phases P on P.`id` = T.`phase_id`
GROUP BY
P.id
but that shows invalid data. (For example, phase_id has a qty of 1 but doesn't show up in the teams table.
Can you point me in the right direction?
Thanks!
The RIGHT JOIN is correct, but you need to use COUNT(T.phase_id) instead of COUNT(*). Otherwise, you're counting the row containing NULL that's generated for the phase with no teams.
Most people prefer to use LEFT JOIN, putting the master table first.
SELECT P.phase_name, P.phase_name, COUNT(T.phase_id)
FROM phase AS P
LEFT JOIN teams AS T ON P.id = T.phase_id
GROUP BY P.id

mysql: order -> limit -> sum... possible?

i am loosing it over the following problem:
i have a table with participants and points. each participant can have up to 11 point entries of which i only want the sum of the top 6.
in this example lets say we want the top 2 of 3
+----+---------------+--------+
| id | participantid | points |
+----+---------------+--------+
| 1 | 1 | 11 |
+----+---------------+--------+
| 2 | 3 | 1 |
+----+---------------+--------+
| 3 | 3 | 4 |
+----+---------------+--------+
| 4 | 2 | 3 |
+----+---------------+--------+
| 5 | 1 | 5 |
+----+---------------+--------+
| 6 | 2 | 10 |
+----+---------------+--------+
| 7 | 2 | 9 |
+----+---------------+--------+
| 8 | 1 | 3 |
+----+---------------+--------+
| 9 | 3 | 4 |
+----+---------------+--------+
as a result i want something like
+---------------+--------+
| participantid | points |
+---------------+--------+
| 2 | 19 |
+---------------+--------+
| 1 | 16 |
+---------------+--------+
| 3 | 8 |
+---------------+--------+
(it should be ordered DESC by the resulting points)
is this at all possible with mysql? in one query?
oh and the resulting participant ids should be resolved into the real names from another 'partcipant' table where
+----+------+
| id | name |
+----+------+
| 1 | what |
+----+------+
| 2 | ev |
+----+------+
| 3 | er |
+----+------+
but that should be doable with a join at some point... i know...
Using one of the answers from ROW_NUMBER() in MySQL for row counts, and then modifying to get the top.
SELECT ParticipantId, SUM(Points)
FROM
(
SELECT a.participantid, a.points, a.id, count(*) as row_number
FROM scores a
JOIN scores b ON a.participantid = b.participantid AND cast(concat(a.points,'.', a.id) as decimal) <= cast(concat(b.points,'.', b.id) as decimal)
GROUP BY a.participantid, a.points, a.id
) C
WHERE row_number IN (1,2)
GROUP BY ParticipantId
Had an issue with ties until I arbitrarily broke them with the id

How to count and group query to get proper results?

I have a problem, please see my database:
-------------------
| id | article_id |
-------------------
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 3 |
| 8 | 3 |
| 9 | 3 |
| 10 | 3 |
And I want to receive something like this (order by votes, from max to min):
---------------------------
| id | article_id | votes |
---------------------------
| 1 | 3 | 5 |
| 2 | 1 | 3 |
| 3 | 2 | 2 |
Could you please help me to write proper sql query?
SET #currentRow = 0;
SELECT #currentRow := #currentRow + 1 AS id, t.article_id, t.c AS `votes`
FROM (
SELECT article_id, count(*) as `c`
FROM table_votes
GROUP BY article_id
) t
ORDER BY t.c DESC
please note that you can't select an id column like this in this context, and your "expected result" is incorrect. I tried to adapt it at a maximum.
cheers
SELECT article_id, COUNT(article_id) AS votes
FROM votes_table
GROUP BY article_id
ORDER BY votes DESC;

Select Distinct from multiple tables with order by

I'm stucked with a Mysql query, can you help me?
I have two tables:
user
id | name
1 | foo1
2 | foo2
3 | foo3
posts
id | id_user | created_at | kind
1 | 2 | 15-03-2011 | a
1 | 2 | 14-03-2011 | b
2 | 3 | 13-03-2011 | a
1 | 2 | 12-03-2011 | b
What I want is to retrieve the latest post of each user (the kind doesn't matter) ordered by de creation date.
How can I do that?
Thank you guys
One possible query is:
SELECT
u.id,
(SELECT MAX(p.created_at) FROM posts AS p WHERE u.id = p.id_user) AS latest
FROM
user AS u;
although the dependent subquery may not be the best solution to this. Example output:
users:
+------+------+
| id | name |
+------+------+
| 0 | test |
| 1 | one |
+------+------+
posts:
+------+---------+------------+------+
| id | id_user | created_at | kind |
+------+---------+------------+------+
| 0 | 0 | 2011-02-05 | a |
| 1 | 1 | 2011-02-06 | b |
| 2 | 0 | 2011-02-03 | a |
| 3 | 1 | 2011-02-02 | b |
+------+---------+------------+------+
output:
+------+------------+
| id | latest |
+------+------------+
| 0 | 2011-02-05 |
| 1 | 2011-02-06 |
+------+------------+
You can also add an ORDER BY latest DESC to the end of the query if you wish to get an ordered list of the latest posts across all user IDs.
Using a GROUP BY on id_user and the max post date ?
Something like that :
SELECT u.name, p.id_user, MAX( p.created_at )
FROM posts AS p
LEFT JOIN user AS u ON u.id
WHERE p.id_user = u.id
GROUP BY id_user