MySQL select rand and exclude users with condition - mysql

I need to select random user_id from "user" table, and completely exclude any user_id if current user have any "ongoing" battles with him battles.status
Query:
SELECT user.id
FROM user
LEFT JOIN battles b ON b.uid = user.id AND b.status <> 'ongoing'
WHERE user.id <> 1
ORDER BY RAND( )
LIMIT 1
But the query is not sufficient, because a user can have multiple battles with specific other users, one of them "ongoing" and the others "finished",
My query should select users from the "finished" row.
Tables structure:
user table:
id name
1 John
2 Sarah
3 Jack
4 Andy
5 Rio
battles table:
id uid uid2 status
1 1 2 finished
2 1 2 ongoing
3 2 3 ongoing
4 1 4 finished
5 3 5 finished
If "my" id = "1",
I want to completely exclude any user I have ongoing battle with him, like "2" in the above case and accept all other ids (i.e.3,4 and 5)

You probably want something along the lines of this:
SELECT foe.*
-- Select yourself and join all other users to find potential foes
FROM `user` AS me
INNER JOIN `user` AS foe
ON (me.id <> foe.id)
-- Here we select the active user
WHERE me.`id` = 1
-- Now we exclude foes we have ongoing battles with
-- (your id could be in either uid or uid2)
AND foe.`id` NOT IN (
SELECT `uid` FROM `battles`
WHERE `uid2` = me.`id` AND `status` = 'ongoing'
UNION ALL
SELECT `uid2` FROM `battles`
WHERE `uid` = me.`id` AND `status` = 'ongoing'
);
This will return a list of users which you do not currently have ongoing battles with. You can customise this to return just one of them using LIMIT and random ordering like in your example.

Related

MySQL join not producing expected results with 'in' function

I have a game_players table like this (other columns omitted for brevity):
game_id user_id
1 1
1 3
2 1
2 2
2 4
My intention is to show the user that's logged in only the games they're involved in (e.g. user 2 should only see game 2).
The "where 2 in(select game_players.user_id from game_players)" bit doesn't appear to be working, I get a list of all the games - including the ones user 2 isn't involved in.
select games.game_id as 'game_id',
games.date_game_started as 'date_started',
users.username as 'username',
users.permanent_id as 'permanent_id',
game_players.user_id as 'user_id'
from games
inner join game_players on games.game_id = game_players.game_id
inner join users on game_players.user_id = users.user_id
where 2 in(select game_players.user_id from game_players)
and games.game_active = 1
and game_players.current_turn = 1
group by(games.game_id)
order by field(game_players.user_id, 2) desc,
games.date_game_started asc
Given my test data, I get this result set:
game_id date_started username permanent_id user_id
1 2021-12-15 13:33:17 userc userc 3
2 2021-12-15 13:35:20 Admin admin 1
I should only be getting the second row, because user 2 is only involved in game 2.
I'll admit that my SQL is a bit rusty, please can you help?
I simplified/broke it down and found the answer. I think... so far so good on my testing of it.
Needed to change:
where 2 in(select game_players.user_id from game_players)
to...
where game_players.game_id in(select game_id from game_players where user_id = 2)

Not able to figure out sql query

i am new to sql and need help with a query. I have two tables user and user_family which contains data like
USER
ID
Date-Of-birth
User_Id
1
2021-05-21
28371
2
2021-04-17
28372
USER_FAMILY
ID
family_detail_id
User_Id
1
1
28371
2
1
28374
3
1
28375
4
2
28372
5
2
28373
6
2
28378
7
2
28379
i want to run a query which checks if current date in equal to someones dob in my user table, if yes i want to return all entries from user_family table which has same family_detail_id to someone whose dob has been matched.
Suppose if the current date is 2021-05-21 then the result should be,
ID
family_detail_id
User_Id
dob
birthday_user_id
2
1
28374
2021-05-21
28371
3
1
28375
2021-05-21
28371
You can use a self-join on the family_detail_id,
select f2.*
from user u join user_family f on f.id=u.id
join user_family f2 on f2.family_detail_id=f.family_detail_id
where u.Date_Of_birth=currdate();
Working Fiddle
I would suggest exists. Assuming that user.id matches to user_family.family_detail_id, then this looks like:
select uf.*
from user_family uf
where exists (select 1
from user u
where u.family_detail_id = u.id and
u.dob = curdate()
);
You may try below query, assuming USER_ID is the linking column between the two tables -
select uf1.*
from user_family uf1
where uf1.family_detail_id in
(select uf.family_detail_id
from user_family uf
inner join user u on u.user_id = uf.user_id
where u.Date-Of-birth = CURDATE()); --DATE(u.Date-Of-birth) = CURDATE()
HTH!

Calculate round(avg) from same table and join

I have two tables,
users
userid fname usertype
1 Steve vendor
2 Peter vendor
3 John normaluser
4 Mark normaluser
5 Kevin vendor
6 Alan vendor
7 Sean vendor
vendor_rating
id userid rating
1 1 4
2 2 3
3 2 2
4 2 4
5 1 3
6 5 2
7 5 2
userid is foreign key.
i want to show all vendors (only usertype vendor) from user table by descending/ascending average rating even if Vendor's rating is not available on table it should show, its information should display at last in descending, at first in ascending.
I want to fetch all users info from first table so i m using left join :
SELECT
users.name,
users.userid,
users.usertype
FROM users
LEFT JOIN (SELECT
ROUND(AVG(rating)) AS rating_avg,
userid
FROM vendor_rating
ORDER BY rating_avg DESC) ven
ON users.usertype = 'vendor'
AND users.userid = ven.userid
ORDER BY ven.rating_avg ASC;
Please help where am i going wrong.
EDIT:
I get this
userid ROUND(AVG(vr.ratings))
28 5
27 4
16 3
26 2
25 0
NULL NULL
NULL NULL
NULL NULL
NULL NULL
if i use
SELECT vr.userid, ROUND(AVG(vr.ratings)) FROM vendor_rating vr
RIGHT JOIN (SELECT users.fname, users.userid, users.usertype FROM users) u
ON u.id = vr.vendor_id WHERE u.usertype = 'vendor' GROUP BY vr.userid,u.fname
ORDER BY round(avg(vr.ratings)) ASC
i get NULL values from users table whose rating is not available in vendor_rating table those should display userids
Try to this
SELECT
vr.userid,
u.fname,
ROUND(AVG(vr.rating))
FROM vendor_rating vr
INNER JOIN users u
ON u.userid = vr.userid
WHERE u.usertype = 'vendor'
GROUP BY vr.userid,
u.fname
ORDER BY round(avg(vr.rating)) ASC
finally i got it
SELECT users.fname, users.userid,users.usertype
FROM users
LEFT JOIN (select ROUND(AVG (ratings)) AS rating_avg,userid FROM
vendor_rating group by userid order by rating_avg desc ) ven
ON users.id=userid
WHERE users.usertype='vendor'
order by rating_avg desc
Thank you all, for sharing views to get idea to solve my problem.

How to make my mysql queries for showing friends feeds?

Here is my table structure.(fun_friends)
id user_id,friend_id,status,createdat,updatedat
1 1 2 1 123456 125461
2 1 3 1 454545 448788
3 2 4 1 565659 898889
4 1 5 1 877878 878788
Here is the table structure of user_uploads
id user_id parent_id category_id title slug tags description video_type source video_link video_thumb
1 2 1 2 fun fun ['4','5'] coolvid 1 ytu link thumb
I need to show the latest upload of my friends
Can you tell me how can i join this tables together? i tried with
SELECT * FROM fun_friends WHERE (user_id= '".$_SESSION['user_row_id']."' AND `status` =1) OR (friend_id= '".$_SESSION['user_row_id']."' AND `status` =1)
and it is showing all friends of logged-in user
You can just join both table using user_id field. sample query bellow will return one record with latest user_uploads.id.
select *
from fun_friends a
inner join user_uploads b on a.user_id = b.user id
order by b.id desc limit 0,1
how about using UNION to get the friends user and wrapping it inside a subquery which later join on the other tabel,
SELECT usr.*
FROM user_uploads usr
INNER JOIN
(
SELECT user_ID AS ID
FROM Fun_Friends
WHERE friend_ID = 'ID_HERE'
UNION
SELECT friend_ID As ID
FROM Fun_Friends
WHERE ser_ID = 'ID_HERE'
) idList ON usr.user_ID = idList.ID

mysql select matching results

I'm trying to find the leagues (lid) where two users are apart of.
Here are my tables:
Table leagues:
*id* lname
--------------
1 Hard C
3 Fun
5 Crazy
Table match:
*userid* *lid*
-----------------
1 1
4 5
1 3
2 1
4 1
4 3
*Are primary keys
match.lid is foreign key to leagues.id (a user cannot not be part of the same league twice)
Here's what I have so far (a start):
SELECT t1.lid, t2.lname
FROM match t1
JOIN leagues t2 on t1.lid = t2.id
So far I managed to join the two tables and get the names. My ultimate goal is to show the lid's where two users are part of the same league, say userid 1 and 4.
userid 1 is a member of lid 1 and 3
userid 4 is a member of lid 5, 1, and 3
Both users meet in league(lid) 1 and 3
So I need a query that shows only the league where both users meet. Like this:
lid lname
--------------
1 Hard C
3 Fun
Since userid 1 and 4 meet in league 1 and 3, the results should show that. I can run two queries for each user and check which leagues both users meet via php, but I think it's more efficient to run one query.
SELECT m1.lid, l.lname FROM
`match` m1, `match` m2, leagues l
WHERE m1.lid = m2.lid AND m1.lid = l.id
AND m1.userid = 1
AND m2.userid = 4
There are a few ways. The most straightforward is:
SELECT id AS lid,
lname
FROM leagues
WHERE id IN
( SELECT lid
FROM match
WHERE userid = 1
)
AND id IN
( SELECT lid
FROM match
WHERE userid = 4
)
;
Another way, which is a bit less direct, but may perform better — you can try it and see — is to use JOIN:
SELECT id AS lid,
lname
FROM leagues
JOIN match AS match1
ON match1.lid = leagues.id
AND match1.userid = 1
JOIN match AS match2
ON match2.lid = leagues.id
AND match2.userid = 4
;