query joins give me repreated results mysql php - php

i have a query in mysql that return me repeated results i want results unique.e.g in my example i have company name it return me repeated name,id.
SELECT
company.name,
company.id,
branchInfo.name,
branches.visible
FROM branches
INNER JOIN users branchInfo ON branches.branchId=branchInfo.id
INNER JOIN users company ON branches.companyId=company.id
WHERE branches.visible=1
it returns me the multiple time repeated data so i want it unique.

You could use either DISTINCT or GROUP BY, they are not the same but in your example you will get the same results.
Use DISTINCT if you just want to remove duplicates. Use GROUPY BY if you want to apply aggregate operators like: AVG, MAX, MIN, SUM, and COUNT
Try this:
SELECT
company.name,
company.id,
branchInfo.name,
branches.visible
FROM branches
INNER JOIN users branchInfo ON branches.branchId=branchInfo.id
INNER JOIN users company ON branches.companyId=company.id
WHERE branches.visible=1
GROUPY BY company.name
Or this:
SELECT
DISTINCT(company.name),
company.id,
branchInfo.name,
branches.visible
FROM branches
INNER JOIN users branchInfo ON branches.branchId=branchInfo.id
INNER JOIN users company ON branches.companyId=company.id
WHERE branches.visible=1;
Group by : clause is used in collaboration with the SELECT statement to arrange identical data into groups. This GROUP BY clause
follows the WHERE clause in a SELECT statement and precedes the ORDER
BY clause.
DISTINCT keyword is used in conjunction with the SELECT statement to eliminate all the duplicate records and fetching only unique
records.
UPDATE
Regarding your question about joins.

You don't need to join multiple times user table. instead, you can write as below:
SELECT
company.name,
company.id,
branchInfo.name,
branches.visible
FROM branches
INNER JOIN users branchInfo ON branches.branchId=branchInfo.id AND branchInfo.id = branches.companyId
WHERE branches.visible=1

Related

Getting columns with the same name from different Mysql tables

I have a table for comments ("event_comments") to different events with the following columns:
post_id
event_id
username
comment
date
I want to be able to retrieve this info from the database and also be able to print the username, first name and last name; for this, I thought of using INNER JOIN, but it is not working for the following reason: I have 3 different profile types (3 different tables) "students", "guardians", "teachers" and when I try to use the INNER JOIN using "username" I get an error message saying that Column 'username' in from clause is ambiguous.
SELECT event_comments.post_id, event_comments.event_id, event_comments.username, event_comments.comment, event_comments.date,
students.first_name, students.last_name, students.picture,
guardians.first_name, guardians.last_name, guardians.picture,
teachers.first_name, teachers.last_name, teachers.picture
FROM event_comments
INNER JOIN students
INNER JOIN guardians
INNER JOIN teachers
USING (username)
ORDER BY date DESC
LIMIT 20
I tried to do this and it worked, but it only shows 1 comment per user; if the user has more than 1 comment then the info is ignored:
SELECT event_comments.post_id, event_comments.event_id, event_comments.username, event_comments.comment, event_comments.date,
students.first_name, students.last_name, students.picture,
guardians.first_name, guardians.last_name, guardians.picture,
teachers.first_name, teachers.last_name, teachers.picture
FROM event_comments
INNER JOIN students
INNER JOIN guardians
INNER JOIN teachers
GROUP BY username
ORDER BY date DESC
LIMIT 20
Does anybody how to get the INNER JOINs to work? is there a better way to do what I want? I hope I explained myself well.
Thanks!
do it like this:
SELECT event_comments.post_id, event_comments.event_id, event_comments.username, event_comments.comment, event_comments.date,
students.first_name, students.last_name, students.picture,
guardians.first_name, guardians.last_name, guardians.picture,
teachers.first_name, teachers.last_name, teachers.picture
FROM event_comments
INNER JOIN students
on event_comments.username=students.username
INNER JOIN guardians
on event_comments.username=guardians.username
INNER JOIN teachers
on event_comments.username=teachers.username
ORDER BY date DESC
LIMIT 20
This will work but assuming that a username from one table is not present in other tables, this will result into 0 rows.
a more logical approach would be to select each table then union it to join every result set like this :
SELECT e.post_id, e.event_id, e.username, e.comment, e_comments.date,
s.first_name, s.last_name, s.picture
from event_comments e
inner join students s
on e.username=g.username
UNION SELECT e.post_id, e.event_id, e.username, e.comment, e_comments.date,
g.first_name, g.last_name, g.picture
from event_comments e
inner join guardians g
on e.username=g.username
UNION SELECT e.post_id, e.event_id, e.username, e.comment, e_comments.date,
t.first_name, t.last_name, t.picture
from event_comments e
inner join teacher t
on e.username=t.username
EDIT:
To explain better about the query it just does this simple steps:
Query all comments from students using username to join post to students
Query all comments from guardians using username to join post to guardians
Query all comments from teachers using username to join post to teachers
Join results from students,guardians, teachers together
You need the using clause for each pair of joins:
FROM event_comments INNER JOIN
students
USING (username) INNER JOIN
guardians
USING (username) INNER JOIN
teachers
USING (username)
In MySQL, an inner join with no on clause is treated as a cross join. In other databases, an on or using clause is required for an inner join.

MySQL: Get common records by user ID

I have to think this is a relatively easy query but I'm stumped. I've got an achievements table, a users table, and a users_achievements table. I want to determine what achievements more than one user share in common based on what exists in the users_achievements table.
SELECT a.id, a.name, a.description, a.badge_path, b.earned_on
FROM achievements AS a
LEFT JOIN users_achievements AS b ON a.id=b.achievements_id
WHERE b.users_id=1
AND b.users_id=2
This returns no results even though the users with ids 1 and 2 share two common records from the users_achievements table based on the achievements_id (so 4 records total--one for each user for each achievement_id). If I use "OR" or "IN" I get records, but that's not inclusive of BOTH ids, just either...I need the query to qualify both IDs.
Here is one way:
SELECT a.id, a.name, a.description, a.badge_path, ua.earned_on
FROM achievements a JOIN
users_achievements ua
ON a.id = ua.achievements_id
WHERE ua.users_id IN (1, 2)
GROUP BY a.id, a.name, a.description, a.badge_path, ua.earned_on
HAVING count(distinct ua.users_id) = 2;
Note the following:
The table aliases a abbreviations. This makes the query easier to read.
The left join should be unnecessary. With such a table structure, the foreign key relationships should match.
The WHERE clause filters for just the two users.
The HAVING clause guarantees that both are present in the results.
Try this
SELECT a.id, a.name, a.description, a.badge_path, b.earned_on, c.earned_on
FROM achievements AS a
JOIN users_achievements AS b ON a.id = b.achievements_id
JOIN users_achievements AS c ON a.id = c.achievements_id
WHERE b.users_id=1 AND c.users_id=2
Here you are selecting what achievements users 1 & 2 have earned in common and when.

MySQL query counting on multiple tables

At the moment, we have 3 queries. In php, we loop over the first, then execute the 2nd multiple times, then which I'd like to have in one single query:
The first query is:
SELECT id FROM users
Then inside looping over those results, the 2nd is
SELECT id AS rid, count(recommendedById) FROM users WHERE id=$id
where $id is users.id from the first query.
The 3rd query is which is executed inside the 2nd loop is:
SELECT count(likes) AS likeCounter FROM posts WHERE author_id=$rid
and likeCounter is summed up to the first query.
Anyone able to bring this into one query?
Desired result
The result should be a row per user with a count of users he recommended and a sum of likes his recommended users got on their posts.
SELECT u.id,COUNT(DISTINCT ruid),sum(p.likes)
FROM users as u
LEFT JOIN (SELECT recommendedById as rid,id as ruid from users) as r ON r.rid = u.id
LEFT JOIN posts p ON p.author_id = ruid
GROUP BY u.id
You can do this:
SELECT u.id AS rid, count(recs.id), count(p.likes) AS likeCounter
FROM users u
LEFT JOIN posts p ON p.author_id=u.id
LEFT JOIN users recs ON recs.recommendedById=u.id
GROUP BY u.id
But a user has an id, and you use id from the users table. Isn't that always 1?

mysql join select explained

I have two tables: 'posts' and 'users' every post has a 'ref_id' column to get the user id who posted it.
Now, I am getting posts this way:
$this->db->query("SELECT * FROM posts WHERE time > '$timeLimit' LIMIT 50");
I can't understand how to join every result to get the poster related data as well. What I am doing right now is basically a loop inside a loop, where foreach of the result, get their user info. But it is pretty obvious that this is very wrong,
Apparently I need to start using joins, but how does one do it? this should be a really simple example to work with, I suppose.
Any help? Thank you.
SELECT posts.*, users.*
FROM posts
INNER JOIN users
ON posts.posted_by = users.id;
Like this:
SELECT
posts.*,,
users.Username
FROM posts
INNER JOIN users ON posts.ref_id = users.user_id;
Explanation:
To JOIN to any tables with each others, there are two things; the JOIN type and the join condition. There are three main types of join:
INNER JOIN, only the rows that match the join condition will be returned from the two tables no more rows. But:
LEFT OUTER JOIN, when you join two tables you will have one on the left of the join keyword and the other one will be in the right:
FROM Table1 <------------- This is the left table.
LEFT OUTER JOIN table2 .... <------------- This is the right table.
In LEFT OUTER JOIN the unmatched rows from the left table will be included in the result set.
RIGHT OUTER JOIN the unmatched rows from the right table will be included in the result set.
CROSS JOIN this will perform a Cartesian product from the two tables.
In our query, the query will reutrn all the users from the users table only if the ref_id equal to the user_id column form the posts table.
For more information and explanations:
A Visual Explanation of SQL Joins.
Another Visual Representation of SQL Joins.
Join syntax in MySQL
SELECT user.name
FROM users
INNER JOIN posts
ON posts.ref_id == user.id
AND posts.time > 50
http://www.w3schools.com/sql/sql_join_inner.asp

Inner Joining with two tables

I need a little help setting up my query. I'm simply trying to access the amount of people who are in the same 'clan' by joining these two tables together, clan, users. Each users has a column 'clan' which is the same as the table clan's column 'roomOwner' and then I'm trying to get the table clan's information along with the amount of members so it would be like: room, roomOwner, members
So basically all I have is this:
SELECT c.*, count(u.clan) AS members FROM clans c inner join users u WHERE c.roomOwner = u.clan ORDER BY members;
It only shows one clan though. Any help please?
Your query has no GROUP BY clause. and I think it's only returning single record right? LEFT JOIN is needed here since there are possibilities that a clan has no member.
SELECT b.roomOwner, COUNT(a.clan) memberCount
FROM clan b
LEFT JOIN users a
ON a.clan = b.roomOwner
GROUP BY b.roomOwner
ORDER BY memberCount
You forgot GROUP BY. Do you have some "id" column in "clans" table? Group by that "id"
SELECT c.*, count(u.clan) AS members
FROM clans c
inner join users u ON c.roomOwner = u.clan
GROUP BY clans.id
And you need LEFT JOIN there instead of INNER JOIN if you want to see info about all clans, even having 0 users.
Perhaps this will help:
select c.*, count(links.id) as members
from clans c
left join users u on c.roomOwner = u,clan
group by u.clan
order by members

Categories