Mysql query for finding followers and following - mysql

Here are the two tables:
1.user
user_id | full_name | username
1 A A_1
2 B B_2
3 C C_3
4 D D_4
5 E E_5
2.user_follower
user_id | follower_id | follow_dtm
2 4 2018-10-09 10:10:10
2 3 2018-01-09 11:10:10
1 5 2018-11-09 07:10:10
4 2 2018-10-09 06:10:10
4 5 2018-10-09 00:10:10
Find follower of user: 2
Output should be:
user_id: 4 fullname: D username: D_4 f_total_flwr: 2 (num of flwr of id-4) following: yes
user_id: 3 fullname: C username: C_3 f_total_flwr: 0 (num of flwr of id-3) following: no
I need a mysql query to find all the followers of a particular user with detail information of the followers from user table and need to know the number of followers each follower has and i also need to if the the particular user also following the follower. Here's what I have tried:
SELECT u.user_id
, u.full_name
, u.username
, COUNT(DISTINCT uf.follower_id) f_total_flwr
, case when b.user_id is null then 'no' else 'yes' end following
FROM user_follower
JOIN user u
ON user_follower.follower_id = u.user_id
LEFT
JOIN user_follower uf
ON u.user_id = uf.user_id
LEFT
JOIN user_follower b
ON b.user_id = user_follower.follower_id
and b.user_id = u.user_id
WHERE user_follower.user_id=2
GROUP
BY u.user_id
ORDER
BY uf.follow_dtm DESC
LIMIT 30
I know I'm getting close ;). The problem is, I'm getting following with a yes value even though the user is not following back.Here is another weird thing - not all but some of them showing yes which should be no .Thanks!

Try this:
select u2.*,b.fcount, case when uf3.user_id is null then 'no' else 'yes' end as connected from user u2 inner join
(
select u.user_id,count(distinct(uf2.follower_id)) fcount
from user u
inner join user_follower uf1 on u.user_id=uf1.follower_id and uf1.user_id=1
left join user_follower uf2 on uf2.user_id=uf1.follower_id
group by u.user_id
) b on u2.user_id=b.user_id
left join user_follower uf3 on u2.user_id=uf3.user_id and uf3.follower_id=1
I tried it using the following data sets:
USER
1,a,abcd
2,b,bcde
3,c,cdef
user_follower
1,2,10
1,3,11
2,3,10
3,1,13
And got the expected result:
2,b,bcde,1,no
3,c,cdef,1,yes

Related

COnditional JOIN query in MySQL

I have two mysql tables
user:
|--------------------------------|
| id | name | type | ruser_type |
|--------------------------------|
| 1 | Admin | a | |
| 2 | | r | c |
|--------------------------------|
customer
|-------------------------|
| id | name | user_id |
|-------------------------|
| 1 | Sam | 2 |
|-------------------------|
If user.type is 'a' or 's', then its admin user whose name is in user table.
If user.type is 'r' and ruser_type is 'c', then its regular user which has a relation in customer table where customer.user_id = user.id
I want a query which would run a conditional join.
If user.type is 'a' or 's', then name would be fetched from user table.
If user.type is 'r' and and ruser_type is 'c', then name would be fetched from customer table with the JOIN condition customer.user_id = user.id.
For this, I have written a query like this:-
SELECT users.fname as adminFname, customers.fname as customerFname, users.type FROM users
LEFT JOIN customers ON (customers.user_id = users.id AND
(
(users.type = 'r' AND users.ruser_type = 'c')
OR users.type = 'a'
OR users.type = 's'
)
)
WHERE users.id = 1
Is there any possibility to optimize the query more?
Also, how can I write this query using Laravel eloquent?
FWIW, I find this marginally easier to read...
SELECT u.fname adminFname
, c.fname customerFname
, u.type
FROM users u
LEFT
JOIN customers c
ON c.user_id = u.id
WHERE u.id = 1
AND (
(u.type = 'r' AND u.ruser_type = 'c')
OR (u.type IN('a','s'))
)
I have written two sql query hope this will help you
SELECT CASE CU.type WHEN 'a' OR 's' THEN CU.name END AS name,
CASE WHEN CU.type = 'r' AND CU.ruser_type = 'c' THEN CR.name END AS cust_name, CU.type
FROM
user AS CU
LEFT JOIN customer AS CR ON CR.user_id = CU.id
In this you'll get result like this,
name cust_name type
Sam r
Admin a
and i have wrote another query like this,
SELECT CASE WHEN CU.type = 'a' OR 's' THEN CU.name ELSE CR.name END AS name, CU.type
FROM
user AS CU
LEFT JOIN customer AS CR ON CR.user_id = CU.id
In this you'll get result like this
name type
Sam r
Admin a
DB File Link
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=b02d931b68a4f70d8b4a84144c60a572
This will give you required result for all users:
SELECT u.fname adminFname
, c.fname customerFname
, u.type
FROM users u
LEFT JOIN customers c
ON (u.type = 'r' AND u.ruser_type = 'c' AND c.user_id = u.id)
Add where condition as required.
You can even simplify it further to get common firstName column in output:
SELECT COALESCE(u.fname, c.fname) firstName, u.type
FROM users u
LEFT JOIN customers c
ON (u.type = 'r' AND u.ruser_type = 'c' AND c.user_id = u.id)

Mysql left join with condition in right table

I have been trying to solve this issue for a while, hope anyone help me. I am having two table, the first table is
Table Name : OnlineTest
OnlineTestId category subcategory
1 English Spelling
2 English Grammar
3 English Antonyms
4 English Synonyms
The second table is
Table Name : UserStatus
Id userId status onlineTestId
1 1 Finished 1
2 1 Not Finished 2
3 2 Not Finished 1
4 2 Finished 3
5 3 Not Finished 4
Result
OnlineTestId userId status
1 1 Finished
2 1 Not Finished
3 null null
4 null null
I have tried this query,
select c.onlinetestid, d.userid, d.status from onlinetest c left join userstatus d on d.onlinetestid = c.onlinetestid
where c.category = 'English' and d.userid = 1;
But this query is bring the first two row of the result and not the last two, in which the userId and status are null.
How to bring the above result?
Place the d.userid = 1 predicate in the ON clause:
select c.onlinetestid, d.userid, d.status
from onlinetest c
left join userstatus d on d.onlinetestid = c.onlinetestid and d.userid = 1
where c.category = 'English'
This will return all rows from onlinetest, having columns of userstatus filled with nulls where predicate d.userid = 1 fails.
You can also use left outer Join as below :
SELECT c.OnlineTestId, d.userId, d.status
FROM OnlineTest AS c LEFT OUTER JOIN
UserStatus AS d ON d.onlineTestId = c.OnlineTestId AND d.userId = 1
WHERE (c.category = 'English')

MySQL: Select newest record from table for every user I talked to

I have 2 tables.
users schema:
private_messages schema:
time_sent is a datetime. All other fields are varchars and ints.
sender_id and receiver_id both refer to id in users.
What I want:
Given a users id, say 1, select the last sent message for every other user (whether the given user sent it or the other user sent it). It should return all the columns of the private_messages table along with the other user's username, and ordered by the time_sent.
The functionality I'm trying to achieve is that of when you open up all of your text messages, and you can see a preview of the last message sent between you and everyone else. This query is killing me because of the fact that the given users id can appear in either the sender_id or the receiver_id. Please help me out with writing the query.
Here is exported sql code to create the tables and their contents (just in case you want something to test with):
users
private_messages
private_messages 2
This should do the trick
SELECT U.username,
U2.username,
IF(PM.sender_id = U.id, 'Sent', 'Received') AS `action`,
PM.message,
PM.time_sent
FROM users U
INNER JOIN private_messages PM ON (PM.sender_id = U.id OR PM.receiver_id = U.id)
INNER JOIN users U2 ON (U2.id = IF(PM.sender_id = U.id, PM.receiver_id, PM.sender_id))
WHERE NOT EXISTS (
SELECT *
FROM private_messages NXT_PM
WHERE NXT_PM.time_sent > PM.time_sent
AND (
( NXT_PM.sender_id = PM.sender_id AND NXT_PM.receiver_id = PM.receiver_id )
OR
( NXT_PM.receiver_id = PM.sender_id AND NXT_PM.sender_id = PM.receiver_id )
)
)
AND U.username = 'Kacy'
ORDER BY time_sent DESC
This returns:
+----------+----------+----------+----------+---------------------+
| username | username | action | message | time_sent |
+----------+----------+----------+----------+---------------------+
| Kacy | liz | Sent | hi again | 2015-03-08 10:47:26 |
| Kacy | Jamie | Sent | hi | 2015-03-07 23:01:18 |
| Kacy | tracy | Received | hi | 2015-03-06 12:04:34 |
+----------+----------+----------+----------+---------------------+
3 rows in set (0.02 sec)
You can do as below technique for getting max per group
select
u1.username as sender,
u2.username as receiver,
m.message,
m.time_sent
from private_messages m
inner join users u1 on u1.id = m.sender_id
inner join users u2 on u2.id = m.receiver_id
left join private_messages m1 on m1.sender_id = m.sender_id
and m1.receiver_id = m.receiver_id
and m1.time_sent > m.time_sent
where m.sender_id = 1
and m1.id is null ;
You can also use
and m1.id > m.id
instead of
and m1.time_sent > m.time_sent
if id is auto-incremented in private_messages table
If you need to see data as both sender and receiver for a given user the condition would be as
where ( m.sender_id = 1 or m.receiver_id = 1 ) and m1.id is null
instead of
where m.sender_id = 1
and m1.id is null ;
http://dev.mysql.com/doc/refman/5.0/en/example-maximum-column-group-row.html

Get two usernames from the same team

Below is the query I am using to get the team information. However, I want also display both usernames assorted with the team. The database is setup using two tables. One contains all of the user information and the other (userLeagues) contains a set of ids, such as userID and teamID.
Example - userLeagues
leagueID | userID | teamID
1 1 1
1 5 1
1 10 2
2 1 1
2 8 1
This is result I am trying to achieve.
leagueID | TeamID | userID1| userID1
1 1 1 5
This would then be outputed as :
leagueID | TeamID | userID1 | userID1
1 Mad Racing driver 1 dirver 5
This is the code I have so far which gets the team but how do I get both driers and their username associated with the same team?
SELECT
u.username
, t.teamName
, t.teamImage
/* File Table */
, f.fileType
FROM
userleague ul
INNER JOIN users u ON u.userID = ul.userID
LEFT JOIN teams t ON t.teamID = ul.teamID
LEFT JOIN fileType f ON f.fileID = t.fileID
WHERE leagueID = 1
GROUP BY ul.teamID
You can do this with min() and max(), if there are only two values:
SELECT t.teamName, t.teamImage, f.fileType,
min(u.username) as user1,
(case when max(u.username) > min(u.username) then max(u.username) end) as user2
FROM userleague ul INNER JOIN
users u
ON u.userID = ul.userID LEFT JOIN
teams t
ON t.teamID = ul.teamID LEFT JOIN
fileType f
ON f.fileID = t.fileID
WHERE leagueID = 1
GROUP BY t.teamName, t.teamImage, f.fileType;

Select from two tables statment

I have two tables:
Users:
id name isSpecial
1 Tal 1
2 Jorden 0
3 John 1
4 Paige 0
Details:
id userId Country zipCode
1 1 Israel 4564
2 3 US 554654
I want to get all the data from Users by the name of Jorden OR if isSpecial is 1 to be shown like this
Result:
id name Country zipCode
1 Tal Israel 4564
2 Jorden
3 John US 554654
I know it's supposed to be a simple query but I can't get the results that I want!
You can use a LEFT JOIN:
SELECT
u.id,
u.name,
u.isSpecial,
d.country,
d.zipCode
FROM Users u
LEFT JOIN Detals d
ON u.id = d.userId
WHERE u.name = 'Jorden'
OR u.isSpecial = 1
Like this
SELECT u.id,u.name,d.country,d.zipCode FROM
Users u
LEFT outer JOIN Details d
ON u.id = d.userId
WHERE u.name = 'Jorden' OR u.isSpecial = '1'
Left join would serve your purpose.
SELECT uObj.ID,uObj.Name,DObj.country, DObj.zipcode FROM users uObj LEFT JOIN Details DObj ON uObj.ID=DObj.userID WHERE uObj.name = 'Jorden'
OR uObj.isSpecial = 1;
Please go through the link below
http://www.w3schools.com/sql/sql_join_left.asp
Hope this helps you out.