Select Distinct from multiple tables with order by - mysql

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

Related

Return the data based on the statuses from other table in SQL

I have table with users:
+-----------+----------+
| id | name |
+-----------+----------+
| 1 | Joe |
| 2 | Tom |
| 3 | Jack |
| 4 | Tim |
+-----------+----------+
and second table with tasks liked with these users:
+--------------+--------------+--------------+
| id | user_id | status |
+--------------+--------------+--------------+
| 1 | 1 | new |
| 2 | 1 | done |
| 3 | 1 | in_progress |
| 4 | 2 | in_progress |
| 5 | 2 | done |
| 6 | 2 | done |
| 7 | 2 | done |
| 8 | 3 | new |
| 9 | 3 | new |
| 10 | 3 | new |
| 11 | 4 | in_progress |
| 12 | 4 | in_progress |
| 13 | 4 | new |
+--------------+--------------+--------------+
Each task could be in 'new', 'in_progress' or 'done' status.
I would like to get a list of user_ids who do not have any tasks in 'new' status but have a task in 'done' status.
Could anyone help me with this? Thanks in advance!
A variety of ways to accomplish this. Here are just a couple:
Query #1: Use CTEs
with done as (
select distinct user_id
from tasks
where status = 'done'
),
new as (
select distinct user_id
from tasks
where status = 'new'
)
select u.id, u.name
from users u
join done d
on u.id = d.user_id
where u.id not in (select user_id from new);
id
name
2
tom
Query #2: No CTEs
select id, name
from users
where id in (select user_id from tasks where status = 'done')
and id not in (select user_id from tasks where status = 'new');
id
name
2
tom
View on DB Fiddle
select u.id , u.name,t.status from users u
left join tasks t on t.user_id = u.id
where t.status<>'new';

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.

MySQL nested Select statement with subquery

I am struggeling with a database query for 2 Hours now.
There is the following database structure:
article table
+---------------+-------------+
| id | ordernumber |
+---------------+-------------+
| 1 | 3243 |
| 2 | 3344 |
| 3 | 3423 |
| 4 | 7687 |
+---------------+-------------+
variant table
+----+-----------+-------+-------+
| id | articleId | stock | price |
+----+-----------+-------+-------+
| 1 | 1 | 3 | 10,99 |
| 2 | 1 | 0 | 10,99 |
| 3 | 1 | 1 | 10,99 |
| 4 | 2 | 0 | 11,99 |
| 5 | 2 | 0 | 11,99 |
| 6 | 2 | 1 | 11,99 |
+----+-----------+-------+-------+
I want to get all Articles where all but one variant have 0 stock.
Is this even possible with a plain sql statement? I tried with a subquery, but without success, since the subquery gets executed first and I would need to pass values from the current record of the resultset of the outer query.
Any help is much appreciated.
Edit:
Expected Result:
+----+-------------+
| id | ordernumber |
+----+-------------+
| 2 | 3344 |
+----+-------------+
If you want the full information for the variant:
select v.*
from variants v
where v.stock > 0 and
not exists (select 1
from variants v2
where v2.articleID = v.articleID and
v2.stock > 0 and
v2.id <> v.id
);
Note: this assumes that the duplicated "5" is a typo and that the ids really are unique in the table.
This can be done using group by and having.
select articleID
from variants
group by articleID
having count(*) - 1 = count(case when stock = 0 then 1 end)

How can I determine which user is the top one in the specific tag?

I have a question and answer website like stackoverflow. Here is the structure of some tables:
-- {superfluous} means some other columns which are not related to this question
// q&a
+----+-----------------+--------------------------+------+-----------+-----------+
| id | title | body | type | related | author_id |
+----+-----------------+--------------------------+------+-----------+-----------+
| 1 | How can I ... | I'm trying to make ... | q | NULL | 3 |
| 2 | | You can do that by ... | a | 1 | 1 |
| 3 | Why should I .. | I'm wonder, why ... | q | NULL | 1 |
| 4 | | First of all you ... | a | 1 | 2 |
| 5 | | Because that thing ... | a | 3 | 2 |
+----+-----------------+--------------------------+------+-----------+-----------+
// users
+----+--------+-----------------+
| id | name | {superfluous} |
+----+--------+-----------------+
| 1 | Jack | |
| 2 | Peter | |
| 3 | John | |
+----+--------+-----------------+
// votes
+----+----------+-----------+-------+-----------------+
| id | user_id | post_id | value | {superfluous} |
+----+----------+-----------+-------+-----------------+
| 1 | 3 | 4 | 1 | |
| 2 | 1 | 1 | -1 | |
| 3 | 2 | 1 | 1 | |
| 4 | 3 | 2 | -1 | |
| 5 | 1 | 4 | 1 | |
| 6 | 3 | 5 | -1 | |
+----+--------+-------------+-------+-----------------+
// tags
+----+------------+-----------------+
| id | name | {superfluous} |
+----+------------+-----------------+
| 1 | PHP | |
| 2 | SQL | |
| 3 | MySQL | |
| 4 | HTML | |
| 5 | CSS | |
| 6 | C# | |
+----+------------+-----------------+
// q&aTag
+-------+--------+
| q&aid | tag_id |
+-------+--------+
| 1 | 1 |
| 1 | 4 |
| 3 | 5 |
| 3 | 4 |
| 4 | 6 |
+-------+--------+
Now I need to find top users in a specific tag. For example, I need to find Peter as top user in PHP tag. Because his answer for question1 (which has PHP tag) has earned 2 upvotes. Is doing that possible?
Try this:
select q1.title, u.id, u.name, sum(v.value) total from `q&a` q1
left join `q&atag` qt ON q1.id = qt.`q&aid`
inner join tags t ON qt.tag_id = t.id
left join `q&a` q2 ON q2.related = q1.id
left join users u ON q2.author_id = u.id
left join votes v ON v.post_id = q2.id
where t.name = 'PHP'
group by q1.id, u.id
and here is a simple divided solution:
Let us divide it into sub queries:
get the id of the tag you will search for: select id from tags where name = 'PHP'
get the questions with this tag: select 'q&aid' from 'q&aTag' where tag_id = 1.
get the ids of answers for that question: select id, author_id fromq&awhere related in (2.)
get the final query: select user_id, sum(value) from votes where post_id in (3.) group by user_id
Now combining them all give the result:
select user_id, sum(`value`) total from votes
where post_id in (
select id from `q&a` where related in (
select `q&aid` from `q&aTag` where tag_id IN (
select id from tags where name = 'PHP'
)
)
)
group by user_id
you can add this at the end if you want only one record:
order by total desc limit 1

Join two table mysql query return all user list values?

Join two table MySQL query return all user list values.
Please correct this query or provide some query.
Table1 : users
+---------+------------+-----------+
| user_id | user_name | cource_id |
+---------+------------+-----------+
| 1 | ramalingam | 1,2,3,4 |
| 2 | yuvi | 1 |
| 3 | Saravanan | 1,2,3 |
| 4 | gandhi | 1 |
+---------+------------+-----------+
Table2 : course
+-----------+-------------+
| cource_id | cource_name |
+-----------+-------------+
| 1 | php |
| 2 | wordpress |
| 3 | seo |
| 4 | magento |
+-----------+-------------+
Output
--------------------------------------
user_id | user_name | cource_id
--------------------------------------
1 | ramalingam| php,wordpress,seo,magnto
2 | yuvi | php
3 | Saravanan | php,wordpress,seo
4 | gandhi | php
This my query
SELECT u.user_id,u.user_name, GROUP_CONCAT(c.cource_name)as course_name
FROM users as u
LEFT JOIN course as c ON c.cource_id = u.user_id
Thank you for any help I can get on this...
In general DB design is bad, don't use comma separated lists at all. Hovewer you should use FIND_IN_SET() in your JOIN clause in order to achieve this:
SELECT
u.user_id,
u.user_name,
GROUP_CONCAT(c.cource_name) AS course_name
FROM
users AS u
LEFT JOIN cource AS c ON FIND_IN_SET(c.cource_id, u.cource_id)
GROUP BY
u.user_id,
u.user_name
Output is:
+---------+------------+---------------------------+
| user_id | user_name | course_name |
+---------+------------+---------------------------+
| 1 | ramalingam | php,wordpress,seo,magento |
| 2 | yuvi | php |
| 3 | Saravanan | php,wordpress,seo |
| 4 | gandhi | php |
+---------+------------+---------------------------+
4 rows in set