mysql: sort tables rows using another table's data - php

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;

Related

SQL SELECT Statement for selecting data from two tables using foreign key

I am just tinkering with SQL as I am trying to get into more complex statements. I don't know this qualifies for it or not but please guide how to go about it.
I have looked at JOINS and some question of Multiple Select Statements but unable to understand them correctly.
I have the following two tables:
emp table:
emp_id, name, address, org_id
books table:
id, emp_id, status, org_id
where emp_id in books table is foreign key referencing emp table.
I need to fetch all the records from books table of a particular org. But along with that I need to get all the data of respective employee like name, address along the result.
Please guide me in the right direction.
Thanks
Try this
select B.*,E.name,E.address from books B
inner join employee E
on B.emp_id=E.emp_id
where B.org_id=1;
I took value of of org_id as 1 for test purpose.
SELECT books.id, books.emp_id, books.status, books.org_id, emp.name, emp.address
FROM books
JOIN emp ON emp.emp_id = books.emp_id
WHERE books.org_id = '3'
As the other said, the org_id from emp table makes no sense. You must remove it from the table.
if you want all records from the books table try this
Select b.id,c.emp_id,b.status,e.name,e.address
from emp_table e
Left join books_table b
on(e.emp_id=b.emp_id)
where e.org_id='3' and b.org_id='3'
You can use this query this will gives you all book record with particular org_id along with all employee record
SELECT * FROM emp as e1
LEFT JOIN books as b1 ON e1.emp_id = b1.emp_id WHERE e1.org_id = 'YOUR_ID'
UNION ALL
SELECT * FROM emp as e1
RIGHT JOIN books as b1 ON e1.emp_id = b1.emp_id WHERE e1.org_id = 'YOUR_ID'
The following query should work for you:
SELECT b.id, b.status, b.org_id, e.emp_id, e.name, e.address
FROM Books b LEFT JOIN Employee e
ON e.emp_id = b.emp_id
WHERE b.org_id = 100
This would be the query for org 100.
It appears that your current schema is not normalized very well:
Employee: emp_id, name, address, org_id
Books: id, emp_id, status, org_id
The two tables both store the org_id, which presumably means the same thing.
This query might give you the results you want. You might want to learn more about joins in SQL. A LEFT JOIN gives you all records from one table, and matching records from another.
SELECT books.*,
emp.name AS emp_name,
emp.address AS emp_address,
emp.org_id AS emp_org_id
FROM books
LEFT JOIN emp ON books.emp_id = emp.emp_id
WHERE books.org_id=?
you can use this for all recors both tables :
select * from books
inner join emp on
books.emp_id=emp.emp_id
where books.emp_id=emp.emp_id

how can i select these in mysql

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

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.

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

How do I get count of duplicated values and join the table to retrieve each value's name?

I have two tables, one that contains volunteers, and one that contains venues. Volunteers are assigned one venue each.
The id of the venues table (venues.id) is placed within the volunteers table in the venue_id column (volunteers.venue_id).
I know I could get a count of how many matching values are in the volunteers.venue_id column by
SELECT venue_id, COUNT(*) FROM volunteers GROUP BY venue_id
Why I want to do this: so the user can go in and see how many volunteers are assigned to each venue.
table: volunteers -- columns: id, name, venue_id
table: venues -- columns: id, venue_name
volunteers.venue_id = venues.id
I know this would be a join statement of some sort so it will get a count of each venue, then match up volunteers.venue_id to venues.id and print out the venues.venue_name along with the count.
How would I go about joining the two tables to print out the venue name and next to it, list the count of each volunteer with that venue_id?
This will give you all of the venues, with those having no volunteers showing up with a 0 volunteer_count
select venues.venue_name, count(*) as volunteer_count
from venues
left outer join volunteers
on venues.id = volunteers.venue_id
group by venues.venue_name
[EDIT] I just realized you asked for MySQL. I can't remember if MySQL uses LEFT JOIN or LEFT OUTER JOIN. The syntax above would be correct for SQLSERVER. The key point is the outer join instead of the inner join to get the venues that have no volunteers.
SELECT venues.venue_name, COUNT(volunteers.*) AS cvolun
FROM venues
INNER JOIN volunteers
ON venues.id = volunteers.venue_id

Categories