SQL: Sort on number of row entries and join - mysql

How do I find duplicate entries in a column (like multiple rows in student_id column) and join those to another table with common id (like student_id from another table to get student_name)?
grades:
student_id,grade
6,A
1,B
1,F
7,C
6,A
students:
student_id,student_name
1,roy
6,bob
7,art
so that I can get a joined table of only duplicate student rows on student_id that resembles:
student_id,student_name,grade
6,bob,A
1,roy,B
1,roy,F
6,bob,A
It would be nice to then just return the names of the most recent data frame:
bob
roy

Try this:
select students.student_name
from grades
inner join students on grades.student_id = students.student_id
group by student_name
having count(*) > 1
Example:
create table grades (student_id int, grade char(1));
insert into grades values (6, 'A'), (1, 'B'), (1, 'F'), (7, 'C'), (6, 'A');
create table students (student_id int, student_name varchar(20));
insert into students values (1, 'roy'), (6,'bob'), (7,'art');
select students.student_name
from grades
inner join students on grades.student_id = students.student_id
group by student_name
having count(*) > 1
Result:
student_name
bob
roy
This should result in bob and roy.
Command line on Linux, assuming you have sqlite:
~$ sqlite
SQLite version 2.8.17
Enter ".help" for instructions
sqlite> create table grades (student_id int, grade char(1));
sqlite> insert into grades values (6, 'A');
sqlite> insert into grades values (1, 'B');
sqlite> insert into grades values (1, 'F');
sqlite> insert into grades values (7, 'C');
sqlite> insert into grades values (6, 'A');
sqlite>
sqlite> create table students (student_id int, student_name varchar(20));
sqlite> insert into students values (1, 'roy');
sqlite> insert into students values (6,'bob');
sqlite> insert into students values (7,'art');
sqlite>
sqlite> select students.student_name
...> from grades
...> inner join students on grades.student_id = students.student_id
...> group by student_name
...> having count(*) > 1;
roy
bob
sqlite>

Find duplicates and then join it back for more information:
SELECT s.student_id, s.student_name
FROM student s
INNER JOIN
(SELECT g.student_id
FROM grades g
GROUP BY g.student_id
HAVING COUNT(*) > 1) dups
ON s.student_id = dups.student_id

Related

Error code 1111: says invalid use of group function

Im trying to use
select Suppliers.sid
from Suppliers
left join Catalog on Suppliers.sid=Catalog.sid
where Catalog.cost>avg(Catalog.cost);
but im getting error code 1111:
Unsure what's going on with my database. Im very nice to sql and just having issues getting this to work.
CREATE DATABASE CSC123Lab2;
USE CSC123Lab2;
CREATE TABLE Suppliers (
sid CHAR(20),
sname CHAR(20),
address CHAR(20),
pid CHAR(20)
);
CREATE TABLE Parts (
pid CHAR(20),
pname CHAR(20),
color CHAR(20),
sid CHAR(20)
);
CREATE TABLE Catalog (
sid CHAR(20),
pid CHAR(20),
cost REAL
);
ALTER TABLE Suppliers ADD PRIMARY KEY (sid);
ALTER TABLE Parts ADD PRIMARY KEY (pid);
INSERT INTO Suppliers (sid, sname, address) VALUES (1, "carvel", "1234 Main Street");
INSERT INTO Suppliers (sid, sname, address) VALUES (2, "coldstone", "5678 Pine Street");
INSERT INTO Suppliers (sid, sname, address) VALUES (3, "ralphs", "9876 Oak Street");
INSERT INTO Suppliers (sid, sname, address) VALUES (4, "Acme Widget", "4321 Maple Street");
INSERT INTO Parts (pid, pname, color) VALUES (1, "hammer", "red");
INSERT INTO Parts (pid, pname, color) VALUES (2, "screwdriver", "pink");
INSERT INTO Parts (pid, pname, color) VALUES (3, "nails", "green");
INSERT INTO Parts (pid, pname, color) VALUES (4, "screws", "teal");
INSERT INTO Catalog (sid, pid, cost) VALUES (1, 3, 32);
INSERT INTO Catalog (sid, pid, cost) VALUES (4, 1, 10);
INSERT INTO Catalog (sid, pid, cost) VALUES (4, 3, 48);
INSERT INTO Catalog (sid, pid, cost) VALUES (2, 4, 24);
select Suppliers.sid
from Suppliers
left join Catalog on Suppliers.sid=Catalog.sid
where Catalog.cost>avg(Catalog.cost);
DROP TABLE Catalog;
DROP TABLE Parts;
DROP TABLE Suppliers;
DROP DATABASE CSC123Lab2;
use group by and do filter in next level
with cte as
(select Suppliers.sid,avg(Catalog.cost) as avg_val
from Suppliers
left join Catalog on Suppliers.sid=Catalog.sid
group by Suppliers.sid
) select a.sid
from Catalog a join cte on a.sid=cte.sid
where a.cost>avg_val
I think you just want a window function:
select s.sid
from Suppliers s join
(select c.*, avg(c.cost) over () as avg_cost
from Catalog c
) c
on s.sid = c.sid
where c.cost > c.avg_cost;
Note, though, that you don't really need the left join. The where clause turns the left join into an inner join.
Then, you don't need the join at all, because sid is in both tables:
select c.sid
from (select c.*, avg(c.cost) over () as avg_cost
from Catalog c
) c
where c.cost > c.avg_cost;
If you prefer, you could express this using a subquery:
select c.sid
from Catalog c
where c.cost > (select avg(c2.cost) from catalog c2);

unknown column in where clause in sql

SELECT *
FROM subjects
INNER JOIN entries ON entries.subject_id= subjects.subject_id
INNER JOIN students ON entries.student_id=students.student_id
WHERE subjects.exam_board LIKE ‘OCR’;
when i execute this the error unknown column 'OCR' in where clause
The following is my subject table
INSERT INTO subjects
(subject_id, subject_name, level_of_entry, exam_board)
VALUES
(1, 'chemistry', 'AS', 'OCR');
INSERT INTO subjects
(subject_id, subject_name, level_of_entry, exam_board)
VALUES
(2, 'biology', 'GCSE', 'AQA');
INSERT INTO subjects
(subject_id, subject_name, level_of_entry, exam_board)
VALUES
(3, 'music', 'GCSE', 'Edexcel');
the below is my students table
INSERT INTO students
(student_id,first_name,middle_name,last_name,email,password,reg_date)
VALUES
(NULL, 'Tom', 'Michael', 'ford', 'tom#yahoo.com','tom1234','2003/12/08');
INSERT INTO students
(student_id,first_name, middle_name, last_name, email, password, reg_date)
VALUES
(NULL, 'michael', 'scoffield', 'burrows', 'lincoln#yahoo.com', 'lincoln1234', '2001/12/16');
You have to use '(single quote) sign insted of ` in like clause hope below code will help you
SELECT *
FROM subjects
INNER JOIN entries ON entries.subject_id= subjects.subject_id
INNER JOIN students ON entries.student_id=students.student_id
WHERE subjects.exam_board LIKE 'OCR';

MySQL find ids for which there is no existing row

I have three tables :
1. Person (person_id, name) : (1, "Test1"), (2, "Test2"), (3, "Test3")
2. Role (role_id, description) : (1, "Admin"), (2, "Designer"), (3, "Developer") ..
3. PersonRoles (person_id, role_id) : (1 , 1), (1, 2), (2, 3), (2, 1), (3, 1)
Is it possible in MySQL with a query to get the ids of the people for which there`s no row with exact role in the PersonRoles table. For Example if I want to check for "Designer" role the query should return ids: 2 and 3
Here is your solution:
select person_id from Person
where person_id not in
(select person_id from Role r
inner join PersonRoles pr on pr.role_id=r.role_id
where r.description='Designer')
You could use the not exists operator:
SELECT *
FROM Person p
WHERE NOT EXISTS (SELECT *
FROM Role r
JOIN PersonRoles pr ON r.role_id = pr.role_id
WHERE r.description = 'Designer' AND
pr.person_id = p.person_id)

How connect two SQL tables that don't have common columns using third table, which contains columns of those both

I need to build SQL query to get all users metadata (meta) from signup table which id is in courses_history table.
The problem is that signup table don't have user_id but does have user_login and courses_history have only user_id.
There is the third table - users, which holds user_id and user_login but I don't know how to connect all 3 table in the right way
CREATE TABLE users
(`user_id` int, `user_login` varchar(7), `description` varchar(55));
INSERT INTO users
(`user_id`, `user_login`, `description`)
VALUES
(100, 'user_1', 'userdataxxxx'),
(201, 'user_2', 'userdatayyyy'),
(301, 'user_3', 'userdatazzzz');
CREATE TABLE signups
(`id` int, `user_login` varchar(7), `meta` varchar(55));
INSERT INTO signups
(`id`, `user_login`, `meta`)
VALUES
(1, 'user_1', 'metaxxxxx'),
(2, 'user_2', 'metayyyy'),
(3, 'user_3', 'metazzzzz');
CREATE TABLE courses_history
(`id` int, `user_id` int, `stuff` varchar(55), `course_id` int);
INSERT INTO courses_history
(`id`, `user_id`, `stuff`)
VALUES
(1, 301, 'stuffxxx', 10),
(2, 301, 'stuffyyyy', 11),
(3, 100, 'stuffzzzz', 22);
(4, 201, 'stuffzzzz', 66);
(5, 201, 'stuffzzzz', 88);
Thanks
SELECT ch.id, u.user_login, su.meta
FROM signups su
INNER JOIN users u ON su.user_login = u.user_login
INNER JOIN courses_history ch ON u.user_id = ch.user_id
SELECT
s.meta
FROM
signups AS s
INNER JOIN courses_history AS ch
ON s.id = ch.id
INNER JOIN users AS u
ON ch.user_id = u.user_id
You can pull whatever data you want out of all three of the tables with this, but I believe this illustrates the point well enough.
Select *
From 1st_table
Inner join CommonTable On common_field = 1stField
Inner join 2nd table on CommonField = 2ndfield

MySQL query returning detailed group_contact information (with join)?

I have query which return me color of the owner and his pet's numbers. How to return instead of
[Red][1,2]
someting more detailed like
[Red][Rufus, Bali]
It's name of pet with join on id of the pet. Is possibile to make another Columns on every pet name? (without using few selects of courst)
CREATE TABLE pet (id INT, name VARCHAR(20));
insert into pet values (1,"Rufus");
insert into pet values (2,"Bali");
insert into pet values (3,"Lolo");
CREATE TABLE own (id INT, own_name VARCHAR(20), own_color VARCHAR(20));
insert into own values (1,"Me", "Red");
insert into own values (2,"Other owners" ,"Green");
CREATE TABLE pet_owner (id INT, id_pet INT, id_own INT);
insert into pet_owner values (1, 1, 1);
insert into pet_owner values (2, 2, 1);
insert into pet_owner values (3, 3, 2);
DROP procedure if exists `pet`;
DELIMITER $$
CREATE procedure `pet`()
BEGIN
set #param = 1;
select o.own_color as color,
(select group_concat(id_pet) from pet_owner po where po.id_own = #param) as pets
from own o
where o.id = #param;
END$$
call pet;
select o.own_color as color,
(select group_concat(p.name) from pet_owner po join pet p ON p.id = po.id_pet where po.id_own = #param) as pets
Try the following--the keys are the aggregate GROUP_CONCAT function and the GROUP BY clause:
select o.own_color as color, group_concat(p.name) as pet_names
from own o
inner join pet_owner po on o.id = po.id_own
inner join pet p on po.id_pet = p.id
group by o.id;