I have the following query:
SELECT u.first_name, o.created_at
FROM user AS u
INNER JOIN order AS o ON o.user_id = u.id
GROUP BY u.id
The data structure looks like this:
user 1
order 1
order 2
order 3
user 2
order 1
user 3
order 1 order 2
user 4
order 1 order 2 order 3 order 4 order 5
Currently the query is returning data as follow:
user 1 > order 1
user 2 > order 1
user 3 > order 1
user 4 > order 1
but I would like to have all last items of user order, as example below:
user 1 > order 3
user 2 > order 1
user 3 > order 2
user 4 > order 5
Is there a way to get this nicely?
I need to retrieve last order of each user to generate the report.
Try this query :-
SELECT u.first_name, o.created_at
FROM user AS u
INNER JOIN order AS o ON o.user_id = u.id
Where o.created_at=(SELECT MAX(o2.created_at)
FROM order o2
WHERE o.user_id = o2.user_id);
GROUP BY u.id
this SELECT MAX(o2.created_at) use for get MAX created_at
SELECT u.first_name, max(o.created_at) as max_created_at
FROM user u
INNER JOIN order AS o ON o.user_id = u.id
GROUP BY u.id
Related
I have searched for the issue but could not have a working solution.
I have 3 tables: User, Post, Comments.
select u.id user
, p.id post
, c.id comm
from USer u
join Post p
on u.id = p.user_id
join Comments c
on p.id = c.post_id;
This gives me an output with 3 columns that relates a user with the posts they have and the comments received on each.
The o/p is like:
user post comm
1 1 4
1 1 5
1 1 7
1 1 8
2 5 11
2 5 12
2 7 13
I wanted to find the user with the maximum number of overall comm. For this the GROUP BY on user is not working. What could be an alternative for the task?
You can use GROUP BY, ORDER BY, and LIMIT:
select p.user_id, count(*) as num_comments
from Post p inner join
Comments c
on p.id = c.post_id
group by p.user_id
order by num_comments desc
limit 1;
Note that because you only want the user id, you do not need the user table, because user_id is in post.
I have a database with two tables: users and payments.
Each user has many payments and each payment can be successful or failed.
I need to write a query to get all the users who failed the last 4 payments.
This is what I tried so far:
select *
from users u
where u.id in(
select p.user_id
from payments
where p.status = 'failed'
group by p.user_id
having count(p.id) = 4
);
But as you can see this is not only checking for the last 4 payments, but all of them. So, it is returning the users that have failed 4 payments (in global, not only the last 4).
I don't know if it is important but the fields on the tables are:
users:
id | name | email | password
payment:
id | date | status | user_id
| | (can be success or failed) | (FK)
Update:
This sqlfiddle will help to understand what I need.
The query is returning all users with 4 failed payments. But I only need the users whose 4 most recent payments failed. In this case it will be only user with id 5
This works
SELECT x.user_id, count(*) as cnt
FROM (
SELECT a.user_id, a.date, a.status FROM payment AS a WHERE
(SELECT COUNT(*) FROM payment AS b
WHERE b.user_id = a.user_id AND b.date >= a.date) <= 4
ORDER BY a.user_id ASC, a.date DESC) AS x
WHERE x.status = 'failed'
GROUP BY x.user_id
HAVING cnt >=4;
If you want the users, whose last 4 transactions were failed (only last 4, not total 4) then following query should get the job done:
select u.* from users u
where
id in
(select p.user_id from payment p
where (select count(*) from payment p1
where p.user_id = p1.user_id
and p.date <= p1.date
order by p1.user_id asc,p1.date desc
) <= 4
and p.status <> 'success'
group by p.user_id
having count(*)>=4);
check the sqlfiddle
Hope it helps!
You want to use the LIMIT keyword, and specify an ORDER.
Try this
select *
from users u
where u.id in(
select p.user_id
from payments
where p.status = 'failed'
group by p.user_id
having count(p.id) = 4
) ORDER BY p.id DESC LIMIT 4;
Not entirely sure what you are trying to do inside the WHERE statement, but ORDER BY p.id DESC LIMIT 4 will retrieve the four most recent rows.
I think you can use a query like this:
select users.id, users.name, users.email, users.password
from users
left join (
select p1.id, p1.date, p1.status, p1.user_id,
count(p2.id) seq -- this count() creates a sequence number for each user ordered by date
from payment p1
left join payment p2
on p1.user_id = p2.user_id -- here I set sequence for each user
and p1.date <= p2.date -- here I set sequence is ordered by data
group by p1.id, p1.date, p1.status, p1.user_id
) t
on users.id = t.user_id
where t.seq < 5 -- Now filter last 4 sequences of each user's payments
and t.status = 'failed'
group by users.id, users.name, users.email, users.password
having count(*) = 4; -- At last filter those have 4 failed in last 4 sequences
[ SQL Fiddle Demo ]
Database structure
Table 'Org_f_a_list'
id org_id user_id date_added
1 1 1 2017-01-01 05:05:05
Table 'Users'
id username last_login
1 Testuser 2017-01-01 05:05:05
Table 'Users_pa'
id user_id summoner_id rank_solo
1 1 1 15
2 1 2 17
My current query
select max(rank_solo) as rank,last_login,username,o.user_id,date_added
from org_f_a_list o
join users u on o.user_id = u.id
join users_pa as p on u.id = p.user_id
where org_id = :org
group by u.id,rank_solo,date_added
order by rank desc
What I want the result to be
user_id user_name rank date_added last_login
1 Testuser 17 date date
My current result
user_id user_name rank date_added last_login
1 Testuser 15 date date
1 Testuser 17 date date
For some reason the group by u.id is not doing anything and I still pull both rows and not just the max rank
Edit : That fixed it. Thanks guys!
remove rank_solo from group by
select max(rank_solo) as rank,last_login,username,o.user_id,date_added
from org_f_a_list o
join users u on o.user_id = u.id
join users_pa as p on u.id = p.user_id
where org_id = :org
group by u.id,date_added
order by rank desc
Rank Should not be part of group by as it is causing forming of two different groups
You can Remove the Rank_solo from the Group By Like this:
select max(rank_solo) as rank,last_login,username,o.user_id,date_added
from org_f_a_list o
join users u on o.user_id = u.id
join users_pa as p on u.id = p.user_id
where org_id = :org
group by u.id,date_added
order by rank desc
You can Use Having with the same Query
select max(rank_solo) as rank,last_login,username,o.user_id,date_added
from org_f_a_list o
join users u on o.user_id = u.id
join users_pa as p on u.id = p.user_id
where org_id = :org
group by u.id,date_added
Having rank_solo = max(ranl_solo)
order by rank desc
I have this query
SELECT DISTINCT u.fbid, u.name,r.points
FROM users u, players_records r
WHERE u.fbid = r.user_id
ORDER BY r.points DESC LIMIT 5
I want to get the top players but only different 5 players, this query is not working it shows duplicated users ids
any help ?
Result for the above query
1112222 Name 1 9310
3334444 Name 2 8380
3334444 Name 2 7010
5555666 Name 3 6080
1112222 Name 1 4890
so the ids are duplicated
It sounds like you want the maximum point per user. So you could do it something like this:
SELECT
users.fbid,
users.name,
maxRecords.points
FROM
users
JOIN
(
SELECT
MAX(players_records.points) AS points,
players_records.user_id
FROM
players_records
GROUP BY
players_records.user_id
) AS maxRecords
ON maxRecords.user_id=users.fbid
ORDER BY
maxRecords.points DESC
LIMIT 5
If I understand you data. Then the output will be like this:
1112222 Name 1 9310
3334444 Name 2 8380
5555666 Name 3 6080
If you need TOP 5 players by points:
SELECT TOP 5 u.fbid, u.name, max(r.points) AS points
FROM users u
LEFT JOIN players_records r ON u.fbid = r.user_id
GROUP BY u.fbid, u.name
ORDER BY points DESC
If you need TOP 5 players by SUM points:
SELECT TOP 5 u.fbid, u.name, SUM(r.points) AS points
FROM users u
LEFT JOIN players_records r ON u.fbid = r.user_id
GROUP BY u.fbid, u.name
ORDER BY points DESC
You could just select max score and group by user.
SELECT u.fbid, u.name, MAX(r.points) max_points
FROM users u, player_records r
WHERE u.fbid = r.user_id
GROUP BY u.fbid, u.name
ORDER BY max_points DESC LIMIT 5
Something like this might resemble what you want.
select fbid, u.name, sum(r.points) totalpoints
from users u join players_records r on u.fbid = r.user_id
group by fbid, u.name
order by totalpoints desc
limit 5
I have a table of users which hold a a users id that they voted for like this:
uid | voted_for
1 | 3
2 | 3
3 | 1
What i'm aiming to do is order uid based on how many people have voted for that uid. But I have no idea how to do it.
So the end result would be:
uid | Total_Votes
3 | 2
1 | 1
2 | 0
Hope you can help explain the best way to structure the SQL for this.
Perhaps something like this will help joining the table on itself:
SELECT u.*, voted_for_cnt
FROM users u
LEFT JOIN (
SELECT voted_for, count(1) voted_for_cnt
FROM users
GROUP BY voted_for
) t ON u.uid = t.voted_for
ORDER BY t.voted_for_cnt DESC
SQL Fiddle Demo
This simple query will produce the output you requested:
select voted_for as uid, count(*) as total_votes
from users
group by 1
order by 2 desc
If you want all data about each user in the output, join users to itself:
select u.*, count(v.uid) as total_votes
from users u
left join users v on v.voted_for = u.uid
group by 1,2,3,4,5 -- put as many numbers here as there are columns in the users table
order by total_votes desc
This second query will give a total_votes score of zero if no one voted for the user.
Alternatively, you can select only those columns you want:
select u.uid, u.name, count(v.uid) as total_votes
from users u
left join users v on v.voted_for = u.uid
group by 1,2
order by 3 desc
```
To return only the winners, do this:
select u.uid, u.name, count(*) as total_votes
from users u
left join users v on v.voted_for = u.uid
group by 1,2
having count(*) = (
select max(c) from (
select count(*) as c from users group by voted_for))
order by 3 desc