Many to many query with 3 tables - mysql

I have 3 tables: WAS, USER and connection table WAS_USER. The thing I would like to achieve is to get all the rows from table WAS and if there are many users to the same WAS I would like to have one row for each one.
for example:
WAS:
id | name
1 | 'was1'
2 | 'was2'
USER:
id | name
1 | 'user1'
2 | 'user2'
WAS_USER:
userId | wasId
1 | 1
2 | 1
So after queering I need to get this:
wasrId | userId | wasName | userName
1 | 1 | 'was1' | 'user1'
1 | 2 | 'was1' | 'user2'
1 | 2 | 'was1' | 'user2'
Ordinary join between the 3 tables will give my only rows from WAS, what I need is some kind of left join on 3 tables.

Ok, here is what worked for me:
SELECT *
FROM
(SELECT * FROM WAS W LEFT JOIN WAS_USER WU ON W.id=WU.wasID) TMP LEFT JOIN USER U ON TMP.userId=U.userId
Don't know about the efficiency though...

Related

SQL: Get top users that follow same users

I have the table followers that looks like this:
id |follower_id|followee_id|
1 | 1 | 2 |
2 | 1 | 3 |
2 | 1 | 4 |
3 | 2 | 3 |
4 | 2 | 4 |
5 | 3 | 2 |
6 | 4 | 6 |
Where follower is a user_id and followee is the user they follow.
How can I find the users that have the most common followees with let's say user 1?
The results need to be ordered by number of common followees.
For example for the current table the results for user 1 would be:
follower_id|common_followees|
2 | 2 |
3 | 1 |
As you can see 4 does not appear in results since it has no common followees with user 1
I hope I explained the problem right.
Thank You.
This is a self-join and aggregation:
select f.follower_id, count(*) as num_common_followees
from followers f join
followers f1
on f.followees = f1.followees and f1.follower_id = 1
group by f.follower_id;
You can add where f.follower_id <> 1. I like to leave that row in as a validation check.

Finding many matches to one row in the same table and getting results from a second table based on the results

I know that the question title may not be quit clear to understand but I try to explain:
users_table:
id | name | admin | property_id
-----------------------------------
1 | x | 1 | 0
2 | y | 1 | 0
3 | z | 0 | 1
5 | t | 0 | 2
6 | u | 0 | 2
7 | o | 0 | 2
users_table has two or more records which are admin and some other records which belong to one of these admin records by matching the property_id with the id. In the end what I want is the admin row data and the count of its properties. This is what should be the output from the first part of the query:
id | name | admin | property_count
-----------------------------------
1 | x | 1 | 1
2 | y | 1 | 3
Until now I know how to get the desired results but here begins the problem.I have another table
sells_table:
id | seller_id | sell_amount
----------------------------
1 | 3 | 250
2 | 5 | 120
3 | 7 | 100
4 | 5 | 200
So this is the logic: every admin has many properties and each property has many sells.
I want all records for each admin from the users_table plus the count of its property_id.
And then query the sells_table in a way where for each property of each admin the number of sells and the sum of the total sells gets calculated.
for example this should be the result for the admin with the id 2 and the name y:
name | properties | property_sells | property_amount
--------------------------------------------------------
y | 3 | 3 | 420
y has 3 properties. Property with id 5 which belongs to y(admin) has two sells and id 7 which also belongs to y(admin) has one sell and the sum of these 3 sells is 420.
I think this is what you want:
select ua.id, ua.name, ua.admin, count(distinct u.id) as property_count,
sum(s.sell_amount) as amount
from users_table ua left join
users_table u
on ua.id = u.property_id left join
sales s
on s.seller_id = u.id
where ua.admin = 1
group by ua.id, ua.name, ua.admin;
http://sqlfiddle.com/#!9/36834d/2
SELECT u.id, U.name, u.admin, COUNT(DISTINCT ut.id) property_count, SUM(st.sell_amount)
FROM users_table u
LEFT JOIN users_table ut
ON u.id = ut.property_id
LEFT JOIN sells_table st
ON ut.id = st.seller_id
WHERE u.admin = 1
GROUP BY u.id, u.admin, u.name

replace the id with the username from an other table in a CROSS JOIN in MySQL

This question is regarding this one: Joining multiple tables to get NOT EQUAL values in MySQL
I want to extend the following query:
SELECT
d.dataid,
d.colors,
u.userid,
u.username
FROM
users u
CROSS JOIN
datas d
WHERE
(u.userid , d.dataid) NOT IN (SELECT
c.userid, c.dataid
FROM
collections c)
AND u.userid = 1
For this data sample:
table datas table users table collections
dataid | colors | addedby userid | username collectionid | userid | dataid
-------------------------- ------------------- ------------------------------
1 | blue | 1 1 | Brian 1 | 1 | 1
2 | red | 1 2 | Jason 2 | 2 | 3
3 | green | 2 3 | Marie 3 | 1 | 3
4 | yellow | 3 4 | 3 | 2
These results are expected:
for Brian
dataid | colors | userid | username
-----------------------------------
2 | red | 1 | Brian
4 | yellow | 1 | Marie
for Jason
dataid | colors | userid | username
-----------------------------------
1 | blue | 2 | Brian
2 | red | 2 | Brian
4 | yellow | 2 | Marie
The row "addedby", which inherits the userid from users, has been added.
At the moment my query replaces the userid from users instead of the addedby from datas with the username.
I really need the userid from datas replaced, not the userid from users. :-)
Does anyone have a clue how to solve this?
Thanks in advance!
cheers
Just join users table once again with datas table. And in the output use username from this join.
SELECT
d.dataid,
d.colors,
uo.userid,
uo.username
FROM
users u
CROSS JOIN
datas d
INNER JOIN
users uo
ON d.added_by = uo.id
WHERE
(u.userid , d.dataid) NOT IN (SELECT
c.userid, c.dataid
FROM
collections c)
AND u.userid = 1
And I believe, that you might even write your query in this way
SELECT u.userid, u.username, d.dataid, d.colors
FROM username u
INNER JOIN datas d
ON u.userid = d.addedby
WHERE d.dataid NOT IN (
SELECT dataid
FROM collections
WHERE userid = 1
)

Querying MySQL tables for a item a user hasnt 'scored' yet

Tables
__________________ ________________________________
|______name________| |____________scores______________|
|___id___|__name___| |_id_|_user-id_|_name-id_|_score_|
| 1 | bob | | 1 | 3 | 1 | 5 |
| 2 | susan | | 2 | 1 | 3 | 4 |
| 3 | geoff | | 3 | 3 | 2 | 3 |
| 4 | larry | | 4 | 2 | 4 | 5 |
| 5 | peter | | 5 | 1 | 1 | 0 |
-------------------- ----------------------------------
Im looking to write a query that returns a RANDOM name from the 'name' table, that the user hasnt scored so far.
So given user '1' for example, it could return 'susan, larry or peter' as user '1' hasnt given them a score yet.
SELECT *
FROM names
LEFT JOIN
votes
ON names.id = votes.name_id
WHERE votes.user_id = 1
AND (votes.score IS NULL);
So far I have this, but it doesnt seem to be working as I would like
(atm it doesnt return a random, but all, but this is wrong)
Any help would be appreciated.
If you are filtering on some field of outer joined table type of join is automatically changed to inner. In your case it's condition
votes.user_id = 1
So you need to move that condition from WHERE to ON
SELECT *
FROM names
LEFT JOIN
votes
ON names.id = votes.name_id and votes.user_id = 1
WHERE (votes.score IS NULL);
Consider moving the condition from WHERE to JOIN ON clause since you are performing an OUTER JOIN else the effect would be same as INNER JOIN
LEFT JOIN votes
ON names.id = votes.name_id
AND votes.user_id = 1
WHERE votes.score IS NULL
ORDER BY RAND();
You could apply :
SELECT name FROM name join scores on name.id=scores.user_id WHERE scores.score=0
You can perform this as a sub-query
SELECT *
FROM names
WHERE id NOT IN (SELECT name_id FROM votes WHERE user_id=1)
ORDER BY RAND()
LIMIT 1

MYSQL - Find records from one table which don't exist in another

I've got the following two SQL tables (in MySQL):
Users
| id | name |
|----|------|
| 1 | Luke |
| 2 | Mark |
| 3 | Lucy |
| 4 | Biff |
User category
| user_id | category_id |
|---------|-------------|
| 1 | 5 |
| 1 | 6 |
| 2 | 5 |
| 2 | 7 |
| 3 | 5 |
I want users that are in User category but not if category id is 6.
In this case Mark and Lucy because Luke is in category 6 too and Biff has no category.
There is a way to do it without subquery and only in one query?
You can group by user_id and eliminate those rows where there is atleast one category_id of 6.
select uc.user_id,u.name
from user_category uc
join users u on uc.user_id = u.id
group by uc.user_id,u.name
having sum(case when category_id = 6 then 1 else 0 end) = 0
Join them and check for difference :
SELECT * FROM users
INNER JOIN user_category ON (user_category.user_id = users.id)
WHERE user_category.category_id <> 6
p.s. using group by is not effective, cuz it says to DB engine to do additional group by operation after gathering data.