SQL - How to Query from 3 tables (query in query?)? - mysql

I want to know how to complete this query correctly.
I wish to export a full list of votes from all ips used by an user.
My database have 3 tables storing the relatives data =>
votes = vote_site_id | vote_ip | vote_time
connexions_ip = adresse_ip | user_id | connexion_time
users = user_id | user_name | user_ip
So actually I have this query to have all connexions_ip from one user =>
SELECT c.adresse_ip, c.user_id, u.user_name
FROM connexions_ip c
LEFT JOIN users u ON u.user_id = c.user_id
WHERE u.user_id = '1'
And this query to have all votes from one user =>
SELECT v.vote_site_id, v.vote_ip, v.vote_time, u.user_name
FROM votes v
LEFT JOIN users u ON u.user_ip = v.vote_ip
WHERE user_id = '1'
I tried with subquery but I have this error "#1242 - Subquery returns more than 1 row"
SELECT v.vote_site_id, v.vote_ip, v.vote_time, u.user_name
FROM votes v
LEFT JOIN users u ON (
SELECT c.adresse_ip
FROM connexions_ip c
LEFT JOIN users u ON u.user_id = c.user_id
WHERE u.user_id = '1'
)
= v.vote_ip
WHERE user_id = '1'
Thanks for your help.

You can join all the table
SELECT c.adresse_ip, c.user_id, u.user_name
, v.vote_site_id, v.vote_ip, v.vote_time
FROM users u
LEFT JOIN connexions_ip c ON u.user_id = c.user_id
LEFT JOIN votes v ON u.user_ip = v.vote_ip
WHERE u.user_id = '1'
I choosed the table users as the base for FROM because is the only table with a condition.

try this:
select a.*,b.* from (SELECT c.adresse_ip, c.user_id, u.user_name
FROM connexions_ip c
LEFT JOIN users u ON u.user_id = c.user_id
WHERE u.user_id = '1')a left join (SELECT u.user_id,v.vote_site_id, v.vote_ip, v.vote_time, u.user_name
FROM votes v
LEFT JOIN users u ON u.user_ip = v.vote_ip
WHERE user_id = '1')b on a.user_id = b.user_id

Related

SQL query to find all users, User 'A' follows and then check if another User 'B' also follows the same users

I want to display all users data, who User 'A' is following. And then further check if User 'B' is also following some users of User 'A'.
I managed to get al users data, who User 'A' is following. But don't understand how to query for the second condition.
Here is my Fiddle link with an example: https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=29a7d1e29f794a8f18a89fe45c06eaa9
You can try to let your User 'B' in a subquery then do OUTER JOIN
SELECT u.*,
IF(friend_id IS NULL,0,1) amIfollowing
FROM users u
LEFT JOIN (
Select friend_id
from friends
where user_id = 5
) f ON f.friend_id = u.id
WHERE u.id IN (SELECT f.friend_id
FROM friends f
WHERE f.user_id = 1)
ORDER BY u.id
sqlfiddle
If I understand correctly you can try to use only one subquery for friends and then use the condition aggregate function to get the result.
SELECT u.id,
u.image_width,
MAX(CASE WHEN f.user_id = 5 THEN 1 ELSE 0 END) amIfollowing
FROM users u
JOIN (
Select friend_id,user_id
from friends
where user_id IN (1,5)
) f ON f.friend_id = u.id
GROUP BY u.id,
u.image_width
ORDER BY u.id
You could use exists here to check if the corresponding IDs exist:
SELECT *,
case when exists (
select * from friends f
where f.friend_id = u.id and f.user_id = 5
) then 1 else 0 end amIfollowing
FROM users u
WHERE u.id IN (SELECT f.friend_id
FROM friends f
WHERE f.user_id = 1);
Example Fiddle
Looks like a JOIN will do, with distinct
SELECT distinct u.*, (f2.user_Id is not null) amIfollowing
FROM users u
JOIN friends f ON u.id = f.friend_id
LEFT JOIN friends f2 on f2.friend_id = f.friend_id and f2.user_id = 5
WHERE f.user_id = 1
ORDER BY u.id

Mysql query returning too many results

I'm working on a project where I need to check if the user liked the post and then use COUNT() on it, if it gives 0 they haven't if it says 1 they have liked it
I tried using this query
SELECT P.id AS id
, U.username AS username
, P.body AS body
, P.timestamp AS timestamp
, COUNT(L.user_id) AS likes
, COUNT(LD.post_id) AS liked
FROM posts AS P
LEFT JOIN users AS U ON U.id = P.user_id
LEFT JOIN followers AS F ON F.user_id = 'user1'
LEFT JOIN likes AS L ON L.post_id = P.id
LEFT JOIN likes AS LD ON LD.post_id = P.id
AND LD.user_id = 'user1'
WHERE F.following_id = P.user_id
OR P.user_id = 'user1'
GROUP BY P.id
My entrys in my likes table are
UserId|PostId|timestamp
user1 |post1 |time
user2 |post1 |time
My problem is it keeps giving a 2 for the count of LD which shouldn't be possible
*Note: In my code I use :user through PDO I don't actually type the id like that
Edit:
$sql = "SELECT P.id AS id, P.user_id AS userid, U.username AS username, U.name AS name, U.verified AS verified, P.body AS body, P.data AS data, P.timestamp AS timestamp, P.type AS type, P.users AS users, COUNT(L.user_id) AS likes, COUNT(DISTINCT LD.post_id) AS liked FROM posts AS P LEFT JOIN users AS U ON U.id = P.user_id LEFT JOIN followers AS F ON F.user_id = :userid LEFT JOIN likes AS L ON L.post_id = P.id LEFT JOIN likes AS LD ON LD.post_id = P.id AND LD.user_id = :userid WHERE F.following_id = P.user_id OR P.user_id = :userid GROUP BY P.id";
$results = DB::query($sql, array(':userid' => $user_id));
I then loop through the results and format them into json
Can you try adding a DISTINCT keyword on the COUNT function for liked column?
COUNT(DISTINCT LD.post_id) AS liked
Most likely the joins are causing the likes table to be duplicated. Thus, we'll only count the unique posts (by post_id) using DISTINCT.

Filter joined results

Imagine the following table structure:
tb.user tb.usergroups tb.group
id id id
name user_id name
group_id
A user can be in multiple groups through the usergroups table.
I want to search for a user by user name and group name. Speaking in examples: user "Bob" is in "GroupA" and in "GroupB". My query so far:
SELECT *
FROM user u
JOIN usergroups ug ON ug.user_id = u.id
JOIN group g ON ug.group_id = g.id
WHERE u.name = 'Bob' AND g.name != 'GroupA'
This isn't exactly what I want; my result still contains Bob, since he's in "GroupB", but I don't want the result to contain Bob at all.
How to do that?
Thanks
I understand you want to select all users named "Bob" that are not in group A but are in group B. This should do it :
SELECT b.*
FROM (SELECT * FROM user u
JOIN usergroups ug ON ug.user_id = u.id
JOIN group g ON ug.group_id = g.id
WHERE u.name = 'Bob' AND g.name = 'GroupB') b
LEFT JOIN (SELECT userid FROM user u
JOIN usergroups ug ON ug.user_id = u.id
JOIN group g ON ug.group_id = g.id
WHERE u.name = 'Bob' AND g.name = 'GroupA') a
ON a.userid=b.userid
WHERE a.userid is NULL
Check this query as i understand you are looking something like this:
SELECT * FROM user AS u
LEFT JOIN usergroups AS ug ON u.id = ug.user_id
LEFT JOIN groups AS gp ON gp.id = ug.group_id
WHERE u.name = 'Bob'
GROUP by ug.user_id
HAVING count(ug.group_id) = 1 AND gp.name !="GROUPA"

MySql Join tables based on field value

Is it possible to do something like this:
SELECT
p.*, u.*
FROM
posts AS p
IF(p.status = 1)
LEFT JOIN users AS u
ON u.id = p.user_id
ELSE
LEFT JOIN pusers AS u
ON u.id = p.user_id
WHERE p.id = 10 ;
Based on post status being true/false join users/pusers table
No, but you can do this:
SELECT p.*,
(case when p.status = 1 then u.col1 else pu.col1 end) as col1
FROM posts p LEFT JOIN
users u
ON u.id = p.user_id and p.status = 1 LEFT JOIN
pusers AS pu
ON pu.id = p.user_id and p.status <> 1
WHERE p.id = 10 ;
In other words, you can join both tables and use the values from the table, based on the condition.

mysql sum using left join on three tables

We have following tables...
users
id, username password email
user_clubs
id, user_id, club_name
sales
id, club_id, amount, admin_fees, dnt
We are trying to get total sum of admin_fees as outstanding for user_id(for example 5), and we tried following...
SELECT u.id, count(c.id), SUM(s.admin_fees) as total_admin_fees
FROM users u
LEFT JOIN user_clubs c ON c.user_id = u.id
LEFT JOIN sales s ON s.club_id = c.id
WHERE u.id = 5
GROUP BY u.id;
Which is only returning results for first row, which is incorrect, Please help to resolve.
here is sql fiddle to test.
thanks
Try this one for user_id = 5 there are two club ids and with amount 2,5 so total should be 7
SELECT u.id, COUNT(c.id), SUM(s.admin_fees) AS total_admin_fees
FROM users u
LEFT JOIN user_clubs c ON c.user_id = u.id
LEFT JOIN sales s ON s.club_id = c.id
WHERE u.id = 5
GROUP BY s.club_id;
for all users you can do this
SELECT u.id, COUNT(c.id), SUM(s.admin_fees) AS total_admin_fees
FROM users u
LEFT JOIN user_clubs c ON c.user_id = u.id
LEFT JOIN sales s ON s.club_id = c.id
GROUP BY u.`id`;
Fiddle