MySQL LEFT JOIN that won't work - mysql

I have a mysql join and for someone reason its returning duplicate fields for image and firstname and lastname. Like it's not joining right.
Here is the SQL
SELECT a.follow_id, a.user_id, a.following, b.firstname, b.lastname, c.firstname, c.lastname, b.image, c.image
FROM followers a
LEFT JOIN candidates b ON a.following = b.user_id
LEFT JOIN donors c On a.following = c.user_id
WHERE a.user_id = 222
LIMIT 9
Both candidates and donors have a firstname and lastname and image, so I need to get those fields, but not duplicate the fields.
My Results
Can someone please tell me what I'm doing wrong?
Thanks in advance.

SELECT a.follow_id, a.user_id, a.following, b.firstname, b.lastname, b.image
FROM followers a
LEFT JOIN candidates b ON a.following = b.user_id
WHERE a.user_id = 222
UNION DISTINCT
SELECT a.follow_id, a.user_id, a.following, c.firstname, c.lastname, c.image
FROM followers a
LEFT JOIN donors c On a.following = c.user_id
WHERE a.user_id = 222
I'm not sure i'm understand your problem correctly.

Your follow_id and following fields are unique. Since you are joining to the candidates and donors tables using the unique following field, you will need to create 2 subqueries that pull the pertinent information from each table as well as the user_id from the followers table.
You can then do your joins from your followers table to each subquery:
SELECT f.user_id,
can.firstname,
can.lastname,
don.firstname,
don.lastname,
can.image,
don.image
FROM followers f
LEFT JOIN (SELECT a.user_id,
a.following,
b.firstname,
b.lastname,
b.image
FROM followers a
INNER JOIN candidates b
ON a.following = b.user_id) can
ON f.user_id = can.user_id
LEFT JOIN (SELECT a.user_id,
a.following,
c.firstname,
c.lastname,
c.image
FROM followers a
INNER JOIN donors c
ON a.following = c.user_id) don
ON f.user_id = don.user_id
WHERE f.user_id = 222
LIMIT 9;

Related

SQL reuse a subquery 'AS' as a parameter for another subquery

I am new to SQL and try to re-use an alias/subquery I made as a parameter for another subquery.
For a certain period of time I want all the customers who have made a purchase, I get the date of the last purchase but now I am trying to pass this date to the invoices in order to get the name of the salesperson associated to this invoice.
So far I have this:
SELECT c.id,
c.firstname,
c.lastname,
c.language,
c.sex,
c.company,
c.city,
c.postal_code,
c.email,
c.created_at,
(SELECT max(`created_at`) FROM invoices WHERE client_id=c.id) AS last_purchase_date,
[...]
FROM
clients c
JOIN
boutiques b ON b.id = c.boutique_id
JOIN
brands br ON br.id = b.brand_id
[...]
and would like something like:
SELECT c.id,
c.firstname,
c.lastname,
c.language,
c.sex,
c.company,
c.city,
c.postal_code,
c.email,
c.created_at,
u.name
(SELECT max(`created_at`) FROM invoices WHERE client_id=c.id) AS last_purchase_date,
(SELECT id FROM invoices WHERE created_at = last_purchase_date) AS last_invoice_id
(SELECT name FROM users u WHERE id=last_invoice.user_id) AS sales_advisor
[...]
FROM
clients c
JOIN
boutiques b ON b.id = c.boutique_id
JOIN
users u ON u.boutique_id = b.id
JOIN
brands br ON br.id = b.brand_id
[...]
Thanks in advance!
Consider migrating those subqueries into derived tables (i.e., queries in FROM or JOIN clauses instead of SELECT clause). In fact, two of those subqueries can become whole tables: invoices and second users.
SELECT c.id,
c.firstname,
c.lastname,
c.language,
c.sex,
c.company,
c.city,
c.postal_code,
c.email,
c.created_at,
u.name,
agg.last_purchase_date,
i.id AS last_invoice_id,
u2.name AS sales_advisor
[...]
FROM
clients c
JOIN
boutiques b ON b.id = c.boutique_id
JOIN
users u ON u.boutique_id = b.id
JOIN
brands br ON br.id = b.brand_id
JOIN
(
SELECT client_id, max(`created_at`) as last_purchase_date
FROM invoices
GROUP BY client_id
) agg
ON c.id = agg.client_id
JOIN
invoices i ON i.client_id = agg.client_id
AND i.created_at = agg.last_purchase_date
JOIN
users u2 ON u2.id = i.user_id
[...]

How to show usernames using GROUP_CONCAT?

I am trying to figure out how to show usernames instead of userid's in a mysql query that users GROUP_CONCAT. The following query works but shows user id's. How can I show usernames instead?
The query
SELECT p.user_name, p.user_id, up.file, GROUP_CONCAT(c.userid)
FROM tbl_uploads up
LEFT JOIN tbl_users p ON up.user_id = p.user_id
LEFT JOIN tbl_collab c ON up.file = c.file
GROUP BY up.file
Results
user_name | user_id | file | GROUP_CONCAT(c.userid)
Peter 5 pic_1.jpg 2,5
Mary 6 pic_2.jpg 6
julian 2 pic_3.jpg (null)
Join the users table one more time, and get the usernames from there:
SELECT p.user_name, p.user_id, up.file, GROUP_CONCAT(cp.user_name)
FROM tbl_uploads up
LEFT JOIN tbl_users p ON up.user_id = p.user_id
LEFT JOIN tbl_collab c ON up.file = c.file
LEFT JOIN tbl_users cp ON cp.user_id = c.userid
GROUP BY up.file
Presumably, tbl_users has user names. If so, use that for the GROUP_CONCAT():
SELECT up.file, GROUP_CONCAT(p.username)
FROM tbl_uploads up LEFT JOIN
tbl_users p
ON up.user_id = p.user_id LEFT JOIN
tbl_collab c
ON up.file = c.file
GROUP BY up.file;
Note I removed p.username from the SELECT. In general, in an aggregation query, all columns/expressions should either be in the GROUP BY or arguments to aggregation functions.

SQL Join with MAX().

I have two tables, users and contestants. I'm trying to select the max contestant ID that has a profile picture(which is on the user table)
Heres my terrible SQL:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) WHERE u.thumbnail IS NOT NULL
The error currently is: #1248 - Every derived table must have its own alias.
This confuses me since Users has an alias of u, and contestants has an alias of c..
What am I doing wrong here? I'm guessing a lot so some help would be really appreciated!
Whenever you are performing a join operation, you are actually joining two table. The subquery you wrote here, for instance, is working as a separate table. Hence, you have to use an alias to this table. That's the reason behind your error message.
Your query:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) WHERE u.thumbnail IS NOT NULL
It should contain an alias for the subquery:
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
Let's say, it's T.
So, your query now becomes:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) AS T
WHERE u.thumbnail IS NOT NULL
But what you are trying to achieve, can actually be done in a neater way:
SELECT u.thumbnail, u.id, max(c.id),
FROM users as u
LEFT JOIN contestants as c
on u.id = c.user_id
WHERE u.thumbnail IS NOT NULL
Why make all the fuss when you have a better and neater approach at your disposal?
try this:
SELECT u.thumbnail, u.id
FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
)A
WHERE u.thumbnail IS NOT NULL
i think this should be simple,
SELECT u.thumbnail, u.id
FROM users u
INNER JOIN contestants c
ON u.id = c.users_id
WHERE u.thumbnail IS NOT NULL
ORDER BY c.id DESC
LIMIT 1
This is very simple.
SELECT user.thumbnail, user.id
FROM users user
INNER JOIN contestants cont ON cont.id = cont.users_id
WHERE cont.thumbnail IS NOT NULL
ORDER BY user.id DESC

Select count of users over two tables

I want to count the occurrence of the same user id in two tables.
The jos_findme table has all the users in it. The other two have as well the column "user id".
But I want the overall count in the two tables. I tried this but it does not work?
SELECT
c.user_id, count(c.user_id) AS counter
FROM
jos_findme as c
LEFT JOIN
jos_findme_bestof as b ON b.user_id = c.user_id
LEFT JOIN
jos_findme_pair as p ON p.user_id = c.user_id
WHERE
c.user_id > 0
GROUP BY c.user_id
ORDER BY counter DESC
LIMIT 10
ALL tables have the column "user_id". I just want to count them in the tables "jos_findme_bestof" and "jos_findme_pair"
Correlated subqueries could be useful here:
SELECT c.user_id,
(SELECT Count(*)
FROM jos_findme_bestof b
WHERE b.user_id = c.user_id),
(SELECT Count(*)
FROM jos_findme_pair p
WHERE p.user_id = c.user_id)
FROM jos_findme c
Try this
SELECT c.user_id,
Users1 = (SELECT COUNT(*) FROM jos_findme_bestof b WHERE b.user_id = c.user_id),
Users2 = (SELECT COUNT(*) FROM jos_findme_pair p WHERE p.user_id = c.user_id),
TotalUser = (SELECT COUNT(*) FROM jos_findme_bestof b WHERE b.user_id = c.user_id)
+
(SELECT COUNT(*) FROM jos_findme_pair p WHERE p.user_id= c.user_id)
FROM
jos_findme c
Here,
Users1 will return all users from jos_findme_bestof
Users2 will return all users from jos_findme_pair
TotalUser will be count of both the tables
Hope it would helps you!
Thanks.
Try this:
SELECT c.user_id, (IFNULL(b.bCount, 0) + IFNULL(p.pCount, 0)) AS counter
FROM jos_findme AS c
LEFT JOIN (SELECT b.user_id, COUNT(1) bCount
FROM jos_findme_bestof b
GROUP BY b.user_id
) AS b ON b.user_id = c.user_id
LEFT JOIN (SELECT p.user_id, COUNT(1) pCount
FROM jos_findme_pair p
GROUP BY p.user_id
) AS p ON p.user_id = c.user_id
WHERE c.user_id > 0
GROUP BY c.user_id
ORDER BY counter DESC
LIMIT 10
I think you can do something like this:
SELECT AA.user_id, AA.Acounter + BB.Bcounter
from (SELECT a.user_id, count(a.user_id) AS Acounter
FROM jos_findme_bestof as a
GROUP BY a.user_id) as AA
Join
(SELECT b.user_id, count(b.user_id) AS Bcounter
FROM jos_findme_pair as b
GROUP BY b.user_id) as BB
on AA.user_id = BB.user_id
if you wants all the ids (meaning if there are id's in jos_findme_pair that are not in jos_findme_bestof) - use FULL OUTER JOIN

How can I select from two tables?

If I have these two tables:
table_user
Id name lname
1 Mark Brown
2 Martha Fox
table_score_start:
user_Id score
2 5
table_score_last:
user_Id score
1 3
2 4
How can I show the following query result?
Id name lname score score
1 Mark Brown 3
2 Martha Fox 5 4
I tried
SELECT table_user.Id, table_user.name, table_user.lname, table_score_start.score,
table_score_last.score FROM table_user, table_score_start, table_score_last
but it doesnt work
I also tried
SELECT table_user.Id, table_user.name, table_user.lname, table_score_start.score,
table_score_last.score FROM table_user, table_score_start, table_score_last WHERE table_user.Id = table_score_start.user_Id
I want to show all the records even thought including those that are not in one or two of the tables tables table_score_start and table_score_last
select a.Id, a.name, a.lname, b.score as start_score, c.score as last_score from table_user a
inner join table_score_start b on (a.Id = b.user_Id)
inner join table_score_last c on (a.Id = c.userId)
inner join or left join depends on your needs.
try the below query:
SELECT u.Id, u.name, u.lname, s.score, l.score FROM table_user u,
table_score_start s, table_score_last l WHERE u.id = s.user_id
AND u.id = l.user_id
Or using joins :
SELECT u.Id, u.name, u.lname, s.score, l.score FROM table_user u
INNER JOIN table_score_start s ON (u.id = s.user_id)
INNER JOIN table_score_last l ON ( u.id = l.user_id)
You can read more about MySql JOIN in this article: http://dev.mysql.com/doc/refman/5.0/en/join.html
Use mysql JOIN ....
here is a simple guide for this ...
http://www.copterlabs.com/blog/optimizing-sql-queries-with-joins/
SELECT `user`.*, `start`.score, `last`.score
FROM table_user `user`, table_score_start `start`, table_score_last `last`
WHERE `start`.user_Id = `user`.Id
AND `last`.user_Id = `user`.Id;
Something like this ought to do the trick:
SELECT u.ID, u.name, u.lname, start.score, last.score
FROM table_user AS u LEFT JOIN table_Score_Start AS Start on u.ID = Start.ID
LEFT JOIN table_Score_last AS Last on u.id = Last.ID
It's off the top of my head, but that should get you in the ballpark. You may have to make some MySQL syntax tweaks, I've been working in SQL Server.
When you are running a SELECT against multiple tables, you should also include the JOIN condition between those tables. Here's somewhere to start reading up on JOINS
Try the following. Please also not the use of aliases for the tables, which just makes the code easier to read, but has no impact on the execution.
SELECT u.Id
,u.name
,u.lname
,ss.score
,sl.score
FROM table_user u
INNER JOIN
table_score_start ss
ON ss.user_ID = u.Id
INNER JOIN
table_score_last sl
ON sl.user_ID = u.Id
In other answers I see INNER JOIN, but since you also want to see the records that don't have a start or end score (or both), you should be using a LEFT JOIN like this:
SELECT a.Id, a.name, a.lname, b.score as start_score, c.score as last_score
FROM table_user a
LEFT join table_score_start b on (a.Id = b.user_Id)
LEFT join table_score_last c on (a.Id = c.user_Id)