mysql select a value within a select - mysql

I have an implementation messages system.
My problem is, I would like to know whether a user already has a thread with another user and if so what is the mid
I have a messages_recips table which look like this
---------------------------
| mid | seq | uid | status|
|--------------------------
| 4 | 1 | 1 | A |
| 4 | 1 | 2 | A |
---------------------------
if user id 1 having a thread with user id 2 I hold 2 rows with same mid.
I know I can create 2 sqls to achieve what I'm asking for, but I'm trying to do it in 1 sql.

As noted by Waqar Janjua, the key to this is a self-join query:
SELECT m1.mid
FROM messages_recips AS m1
JOIN messages_recips AS m2 ON m1.mid = m2.mid
WHERE m1.uid = 1
AND m2.uid = 2

I think you have to write a self-join query:
Select u.uid, u1.uid from tablename u
INNER JOIN tablename u1 on u.mid = u1.mid
You will get all the users who have the same mid.
In order to get only user1 and user2 records you have to place a where clause at the end of the query lik this.
Select u.uid, u1.uid from tablename u
INNER JOIN tablename u1 on u.mid = u1.mid
Where ( u.uid In ( 1,2 ) OR u1.uid In ( 1,2 ) ) ;

Related

how to get count items that not exists for user with SQL

I have table user_item
+----+---------+---------+
| id | user_id | item_id |
+----+---------+---------+
| 1 | 1 | 1 |
| 2 | 1 | 3 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
| 5 | 3 | 2 |
+----+---------+---------+
Is it possible to get for each user (except user_id 1) number of items that user_id 1 has and other users don't. The desired output should be:
+---------+-------+
| user_id | count |
+---------+-------+
| 2 | 1 |
| 3 | 2 |
+---------+-------+
Thanks.
Building on Gordon Linoff's answer, here's my take:
select
u.id,
count(*) - count(ui.item_id) cnt
from
users u
join user_items ui1 on ui.id=1
left join user_items ui on ui.user_id=u.id and ui.item_id=ui1.item_id
where
u.id <>1
group by
u.id
We start by taking each user except the one with id=1. Then we multiply each row by each item for user with id=1. Then to each of the resulting rows we try to join the row for the same item of the other user. Then we group them together and count. The total count(*) will always be the number of items that user with id=1 has. The count(ui.item_id) will be the count of items that both users have overlapping. And the difference is the count of items that user with id=1 has that the other user doesn't have.
Hmmmm . . . This is tricky. Let's start by getting the count that match user 1. Assuming user/item pairs are not duplicated:
select ui.user_id, count(ui1.item_id) as match_user_1
from user_items ui left join
user_items ui1
on ui1.item_id = ui.item_id and
ui1.user_id = 1
group by ui.user_id;
Now, let's subtract from the total number of items that the user has:
select ui.user_id, count(*) - count(ui1.item_id) as not_match_user_1
from user_items ui left join
user_items ui1
on ui1.item_id = ui.item_id and
ui1.user_id = 1
group by ui.user_id;
EDIT:
For the reverse, it is pretty much the same idea, but you need to subtract the matches from the total for user 1:
select ui.user_id, count(ui1.item_id) as match_user_1,
uuix.cnt - count(ui1.item_id) as not_match_user_1
from user_items ui cross join
(select count(*) as cnt
from user_items
where user_id = 1
) ui1x left join
user_items ui1
on ui1.item_id = ui.item_id and
ui1.user_id = 1
group by ui.user_id;
Creating the table and populating the table with sample data:
CREATE TABLE user_item
(
id int PRIMARY KEY,
user_id int,
item_id int
);
INSERT INTO user_item VALUES (1,1,1),(2,1,3),(3,2,1),(4,2,2),(5,3,2);
The below query displays the number of items of user_id 1 that other users don't have.
SELECT ui.user_id, (select count(item_id) - count(ui1.item_id) from user_item where user_id = 1) as count
FROM user_item UI
LEFT JOIN user_item ui1 ON ui1.item_id = ui.item_id AND ui1.user_id = 1
WHERE ui.user_id <> 1
GROUP BY ui.user_id
ORDER BY ui.user_id;
Output:
+---------+-------+
| user_id | count |
+---------+-------+
| 2 | 1 |
+---------+-------+
| 3 | 2 |
+---------+-------+
you can try this too..
select u2.user_id, (T.counter - COALESCE(SUM(u1.item_id), 0))counter
From user_item u2
LEFT OUTER JOIN (
SELECT user_id, item_id
FROM user_item
WHERE user_id=1
)u1 ON u2.item_id=u1.item_id
LEFT OUTER JOIN (
SELECT user_id, COUNT(1)counter FROM user_item where user_id=1 group by user_id
)T ON u2.user_id != T.user_id
where u2.user_id!=1
Group by u2.user_id,T.counter

MySQL Query get the last record then join

Lets say I have a table like this:
table account
id | username
1 | myuser123
2 | secretuser
table subscription
id | username | subsStartDate | subsEndDate
1 | myuser123 | 2017-01-19 | 2017-02-19
2 | secretuser| 2017-01-19 | 2017-02-19
3 | myuser123 | 2017-02-19 | 2017-03-19
4 | secretuser| 2017-02-19 | 2017-03-19
How can I get the latest subsEndDate of each user in table account.
I am looking for an output similar to this:
output looking for
id | username | subsStartDate | subsEndDate
3 | myuser123 | 2017-02-19 | 2017-03-19
4 | secretuser| 2017-02-19 | 2017-03-19
To get the row with latest subsEndDate per user you can use following query
select a.*
from subscription a
left join subscription b on a.username = b.username
and a.subsEndDate < b.subsEndDate
where b.id is null
Demo
SELECT a.*
FROM subscription a
JOIN
( SELECT username
, MAX(subsenddate) subsenddate
FROM subscription
GROUP
BY username
) b
ON b.username = a.username
AND b.subsenddate = a.subsenddate;
A variant for the case where order id isn't equals order max_subsEndDate
SELECT s.*
FROM subscription s
JOIN
(
SELECT username,MAX(subsEndDate) max_subsEndDate
FROM subscription
GROUP BY username
) l
ON s.username=l.username AND s.subsEndDate=l.max_subsEndDate
My variant (if order id is equals order max_subsEndDate)
SELECT *
FROM subscription
WHERE id IN(
SELECT MAX(id)
FROM subscription
GROUP BY username
)
A variant with JOIN
SELECT s.*
FROM subscription s
JOIN
(
SELECT MAX(id) max_id
FROM subscription
GROUP BY username
) l
ON s.id=l.max_id
Something like this :
SELECT s.id, s.username, s.subsStartDate, endate as subsEndDate
FROM
subscription s
INNER JOIN
(SELECT id, Max(subsEndDate) as endate
FROM subscription
GROUP BY id) t ON t.id = s.id

Select entries that aren't part of a pair in another table

Tables:
users friends
+-------+----+ +-----+-----+
| name | id | | id1 | id2 |
+-------+----+ +-----+-----+
| user1 | 1 | | 1 | 2 |
+-------+----+ +-----+-----+
| user2 + 2 |
+-------+----+
In my database id1 in the friends table is the dominant column, which means that if id1 = 1 and id2 = 2 then user1 is friends with user2 but not the other way around.
I'm trying to select all users from the users table that don't have X as id1 in friends. This is because I don't want userX to be able to find friends that he's already added.
Here is my failed attempt:
SELECT * FROM users LEFT JOIN friends ON users.id != friends.id2 WHERE friends.id1 = X AND users.id != X;
I added users.id != X since we don't want to return the user himself in a search for other users.
You can use an outer join to do that, you attempt went into the right direction:
select u.*
from users u
left join friends f
on u.id = f.id2
where f.id1 is null
An outer join returns NULL for every non-matched item at least.
using not in() (more efficient than not exists() in mysql)
select *
from users
where id != xi
and id not in (
select id.2
from friends
where friends.id1 = x
)
using not exists()
select *
from users
where id != x
and not exists (
select 1
from friends
where friends.id1 = x
and friends.id2 = users.id
)

How to write this MYSQL Query with count

So i have the following table:
userid | name | referralcode
When users register on the website they put the referralcode of someone else (the referral code is the same number as the userid of someone else)
so im looking for a sql query that will output something like this
20 (this means 20 users have this userid on their referral code) , Gerardo Bastidas, Valencia
10 , Juan Bastidas, Valencia
I want to get all info on user. its all located in the same table.
Try this query:
SELECT yt1.*, COALESCE(yt2.referral_count, 0)
FROM yourtable yt1 LEFT JOIN
(
SELECT t1.userid, COUNT(*) AS referral_count
FROM yourtable t1 INNER JOIN yourtable t2
ON t1.userid = t2.referralcode
GROUP BY t1.userid
) yt2
ON yt1.userid = yt2.userid;
This query does a self-join and will list every user along with the number of referral codes where his userid appears.
This code will do the work in one query. Replace your table name with 'tbName'
Tested and working
SELECT countval, userid, email, address
FROM tbName t1 LEFT JOIN
(
SELECT COUNT(t2.userid) ASs countval, tt.userid AS xx
FROM tbName t2
GROUP BY t2.referralcode
) t3
ON t3.xx = t1.userid
Output:
+-------+-----+------+
| count | uid | name |
+-------+-----+------+
| 3 | 1 | abc |
| 2 | 2 | xyz |
| 5 | 3 | kmn |
+-------+-----+------+

How to count the number of people who choose a particular location?

i need help in select sql statement.
in my mysql database:
location table
serialID(AI)|locations | telephone | address
---------------------------------------------
1 | A
2 | B
3 | C
4 | D
users table
userID | location chosen
-------------------------
1 | A
2 | B
3 | B
I want to count the number of people who choose a particular location and display in the table. So if this particular location have more users choosen as their favourite location, it will move up to the first row. May I know how can I do this?
something like this when it populate into dynamic table ->
location | address | telephone | user's favourable
B | - | - | 2
A | - | - | 1
C | - | - | 0
D | - | - | 0
You could just do a query like this:
SELECT l.locations, l.telephone, l.address, COUNT (u.userID) as `location_count`
FROM location AS l
LEFT OUTER JOIN users AS u on l.locations = u.location_chosen
GROUP BY l.locations
ORDER BY `location_count` DESC
Try something like this:
SELECT l.location, l.address, l.telephone, COUNT(u.userID) AS [users favourable]
FROM location l
LEFT JOIN
users u
ON l.location = u.locationchosen
GROUP BY l.location, l.address, l.telephone
SELECT loc.*, countResult.usersFavourable
FROM location loc
LEFT JOIN
(
SELECT locationChoosen, COUNT(*) `usersFavourable`
FROM users
GROUP BY locationChoosen
) countResult ON loc.locations = countResult.locationChoosen
ORDER BY countResult.usersFavourable DESC, loc.locations
use this:
select count(userId) count,locations,address,telephone
from Table1 Left join Table2
on Table1.locations = Table2.location
group by locations order by count desc ;
see here.. link
SELECT LocationChosen, Count(*) FROM usersTable GROUP BY LocationChosen