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.
Related
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
I have two tables. One is books table. It has two columns. id|title. Another is student_books table. It has two columns student_id|book_id. When a student tries to read a book, I check the student_books table whether the student_id and the book_id matches or not. A student can buy multiple books so there may have multiple entries in student_books table. now I want to show the list of books based on popularity(that has maximum entries in student_books table) on a page. How should I write the SQL query?
You can join books table with student_books and order by count for each book
select b.*
from books b
left outer join student_books s
on b.id = s.book_id
group by b.id, b.title
order by count(s.student_id) desc;
SELECT b.id, b.title
FROM books b
LEFT JOIN students s ON s.book_id = b.id
GROUP BY b.id, b.title
ORDER BY COUNT(s.book_id) DESC;
Imagine that there are two tables called: Customers, Orders.
In Customers we have rows:
id=1 name=Alex key=12
id=2 name=Bob key=13
and in the Orders we have:
id=1 device=phone status=ordered key=12
id=2 device=phone status=delivered key=12
id=3 device=memory status=ordered key=13
id=4 device=memory status=returned key=13
Now I want it to choose the last one for each one of them in the Customers from Orders. Like it should choose Alex's information and the last row that is inserted for him in the Orders table.
How can I make a query for this?
You can do this with aggregation and a join:
select o.*
from customers c left join
orders o
on c.key = o.key left join
(select o.key, max(id) as maxid
from orders o
group by o.key
) ok
on o.id = oo.id;
The aggregation gets the latest value.
Note that key is a reserved word in MySQL (see here). That makes it a lousy column name, so you should change it.
Sounds like you're looking for the group-wise (key) maximum (id) as explained at https://dev.mysql.com/doc/refman/5.6/en/example-maximum-column-group-row.html
I prefer (for no good reason) the LEFT JOIN variant over the uncorrelated sub-query.
Here is a way you can do it
select
c.*,
o.id,
o.device,
o.status
from customer c
join orders o on o.`key` = c.`key`
join (
select max(id) as id,`key` from orders
group by `key`
)o1 on o1.id=o.id
http://www.sqlfiddle.com/#!9/96885/2
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
I'm creating a table that shows all the registered users to which the current user has not yet subscribed to. But once he has subscribed someone, I need to filter that list to exclude those.
Let's say the theres a table called subscribed which lists the User and to whom he is subscribed to.
|UserId||SubscriberID|
Its easy to make it into multiple queries, but I've been unsuccessfully trying to make it into one query, to save an extra loop of MySQL calls.
Here's What I have so far:
SELECT u.UserID, FullName, UserName from users u
LEFT JOIN subscribed t ON
((u.UserName LIKE '%$search%' OR
u.Email LIKE '%$search%') AND
({$_SESSION['ID']} = t.UserID
AND t.FollowerID != u.UserID)
)
I know the last part of the query is wrong, since I only compare if the UserID and the FollowerID don't match for one particular row, not the entire table.
To find a list of results in table A that are not in table B, you have two options. Either use the NOT IN syntax, or LEFT JOIN and look where the PK field in the B table is NULL.
NOT IN example:
SELECT a.id FROM a WHERE a.id NOT IN (SELECT b.id FROM b)
LEFT JOIN example:
SELECT a.id
FROM a
LEFT JOIN b ON (a.id = b.id)
WHERE (b.id IS NULL)