I am finding a hard time to summarize the SQL table.
Objective: from the given tables I have to join and summarize the table.
col1 = Name_of_student,
col2 = Name_of_subject(where she/he scored highest),
col3= highest_number,
col4 = faculty_Name(where she/he scored highest),
col5 = Name_of_subject(where she/he scored lowest),
col6 = lowest marks,
col7 = faculty_Name(where she/he scored lowest)
Note - I have to write only one query for the given output.
There four tables:
Students.
Students_subject.
Faculty.
Marks.
You can copy the code in my SQL script for understanding the tables.
create database university ;
use university ;
create table students (id int auto_increment primary key,
student_name varchar(250) NOT NULL,
dob DATE NOT NULL) ;
create table faculty ( id int auto_increment primary key,
faculty_name varchar(250) NOT NULL,
date_of_update datetime default NOW()) ;
create table Students_subject ( id int auto_increment primary key,
subject_name varchar(250) default 'unknown' NOT NULL,
subject_faculty int not null,
foreign key(subject_faculty) references faculty(id));
create table marks (id int auto_increment primary key,
student_id int NOT NULL,
subject_id int NOT NULL,
marks int NOT NULL,
date_of_update datetime default now() ON UPDATE NOW(),
foreign key(student_id) references students(id),
foreign key(subject_id) references students_subject(id));
insert into students ( student_name, dob) values
('rob', '2001-03-06'),
('bbb', '2001-09-06'),
('rab', '1991-03-06'),
('root', '2001-03-16') ;
insert into faculty(faculty_name) values
('kaka'),
('dope'),
('kallie'),
('kim');
insert into students_subject (subject_name, subject_faculty) values
('maths', 2),
('physics', 3),
('english', 4),
('biology', 1),
('statistics', 2),
('french', 4),
('economics',3);
insert into marks ( student_id, subject_id, marks) values
(1,1,70),
(1,2,60),
(1,3,98),
(1,4,75),
(1,5,90),
(1,6,30),
(1,7,40),
(2,1,70),
(2,2,60),
(2,3,70),
(2,4,105),
(2,5,95),
(2,6,30),
(2,7,10),
(3,1,70),
(3,2,60),
(3,3,70),
(3,4,75),
(3,5,99),
(3,6,30),
(3,7,10),
(4,1,70),
(4,2,60),
(4,3,70),
(4,4,89),
(4,5,99),
(4,6,30),
(4,7,19);
I had written Query myself to work out on this but cannot break it though.
select students.id, table_high.marks, table_high.faculty_name as high_faculty, table_high.subject_name as sub_high,
student_low.marks , student_low.faculty_name as faculty_low, student_low.subject_name as sub_low from students
inner join
(select students.id, students.student_name ,marks.marks, subject_joined.faculty_name, students_subject.subject_name from marks
inner join (select students_subject.id,students_subject.subject_name, faculty.faculty_name, students_subject.subject_faculty
from students_subject left join faculty on students_subject.subject_faculty = faculty.id)
as subject_joined on subject_joined.id = marks.subject_id
inner join faculty on subject_joined.subject_faculty = faculty.id
inner join students_subject on students_subject.id = marks.subject_id
inner join students on students.id = marks.student_id
order by 1, 3 desc) as table_high on table_high.id = students.id
inner join
(select students.id, students.student_name ,marks.marks, subject_joined.faculty_name, students_subject.subject_name from marks
inner join (select students_subject.id,students_subject.subject_name, faculty.faculty_name, students_subject.subject_faculty
from students_subject left join faculty on students_subject.subject_faculty = faculty.id)
as subject_joined on subject_joined.id = marks.subject_id
inner join faculty on subject_joined.subject_faculty = faculty.id
inner join students_subject on students_subject.id = marks.subject_id
inner join students on students.id = marks.student_id
order by 1, 3 ) as student_low on student_low.id = students.id
group by 1 ;
attaching screen of output :
Finally resolved this question!
The basic tweak that was required in summarizing this table is that the sub-table had to be joined with a combination of two columns as group by command just reflects the first row value in the summarized table for non-summarized cols, so reflecting values of max and min was not possible at the same time, to which I created sub tables filtering rows through double column joins and finally joined the table to the main student table.
The main table which was joined is Students.
Sub-Table 1 - hw (which summarized the data for highest)
sub-table 1.2 - high for highest marks tagging.
sub-table 2 - lw ( which summarized the table for the lowest)
sub-table 2.1 - low for minimum marks tagging.
Query >>
select students.id, students.student_name, lw.min_marks, lw.lower_subject, lw.lower_faculty,
hw.high_marks, hw.subject_name as high_subject, hw.faculty_name as higher_faculty
from students inner join
(select high.student_id, high.high_marks, high.subject_id, high.subject_name, high.faculty_name
from
(select marks.student_id, marks.marks as high_marks, sub_with_faculty.subject_id, sub_with_faculty.subject_name,
sub_with_faculty.faculty_name from marks
left join
(select students_subject.id as subject_id, students_subject.subject_name, faculty.faculty_name
from students_subject
left join faculty on students_subject.subject_faculty = faculty.id) as sub_with_faculty
on sub_with_faculty.subject_id = marks.subject_id) as high
inner join (select marks.student_id, max(marks) as marks from marks group by 1) as maximum on
maximum.student_id = high.student_id and maximum.marks = high.high_marks) as hw on
hw.student_id = students.id
inner join
(select low.student_id, low.low_marks as min_marks, low.subject_id as lower_subjectID, low.subject_name as lower_subject, low.faculty_name as lower_faculty
from
(select marks.student_id, marks.marks as low_marks, sub_with_faculty.subject_id, sub_with_faculty.subject_name,
sub_with_faculty.faculty_name from marks
left join
(select students_subject.id as subject_id, students_subject.subject_name, faculty.faculty_name
from students_subject
left join faculty on students_subject.subject_faculty = faculty.id) as sub_with_faculty
on sub_with_faculty.subject_id = marks.subject_id) as low
inner join (select marks.student_id, min(marks) as marks from marks group by 1) as minimum on
minimum.student_id = low.student_id and minimum.marks = low.low_marks) as lw on
lw.student_id = students.id;
This could be a good exercise for someone who's new to MySQL like me.
Related
My tables are
TRANSACTION TABLE
transaction_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
customer_id INT,
inventory_id INT,
kiosk_id INT,
rental_out DATETIME,
rental_proposal INT,
rental_due DATETIME,
rental_cost FLOAT,
rental_in DATETIME,
rental_period INT,
rental_past_due INT,
late_fee INT
INVENTORY TABLE
inventory_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
title_id INT,
title_name VARCHAR(255),
genre_id INT,
genre_name VARCHAR(255),
qty INT
I'm trying to figure out a way in order to create a query that allows the inventory_id from the transaction table to create a count of the genre's of each transaction. My query allows to find the number of genres transacted, but only one at a time.
SELECT COUNT(genre_id)
FROM inventory
INNER JOIN transactions
ON inventory.title_id = transactions.inventory_id
WHERE transactions.customer_id = 1 and inventory.genre_id = 1;
I'd like to figure out a way to join the table multiple times to display the number of times each genre has been rented, being currently existing genres 1, 2, 3, 4, 5, 6
So far, I've come up these queries, but I don't see a logical way to the solution.
SELECT COUNT(A.genre_id) as GENRE_A, COUNT(A.genre_id) as GENRE_B, COUNT(A.genre_id) as GENRE_C FROM inventory A
INNER JOIN transactions D ON A.title_id = D.inventory_id
INNER JOIN transactions E ON A.title_id = E.inventory_id
INNER JOIN transactions F ON A.title_id = F.inventory_id
WHERE A.genre_id = 1 AND A.genre_id = 2 and A.genre_id = 3;
SELECT COUNT(A.inventory_id), COUNT(B.inventory_id), COUNT(C.inventory_id) FROM transactions A, transactions B, transactions C
INNER JOIN inventory D ON A.inventory_id = D.title_id
INNER JOIN inventory E ON A.inventory_id = E.title_id
INNER JOIN inventory F ON A.inventory_id = F.title_id
WHERE A.genre_id = 1 AND B.genre_id = 2 and C.genre_id = 3;
I've tried multiple variations, some of which I've deleted and haven't posted, but I can't seem to figure it out. Is there any solution? Any help would be greatly appreciated. Thank you!
Just use conditional aggregation.
Only 1 join needed.
This will count the transactions for the 3 genres
SELECT
-- trans.customer_id,
COUNT(CASE WHEN inv.genre_id = 1 THEN trans.transaction_id END) AS genre1,
COUNT(CASE WHEN inv.genre_id = 2 THEN trans.transaction_id END) AS genre2,
COUNT(CASE WHEN inv.genre_id = 3 THEN trans.transaction_id END) AS genre3
FROM transactions trans
JOIN inventory inv ON inv.inventory_id = trans.inventory_id
WHERE inv.genre_id IN (1, 2, 3)
-- GROUP BY trans.customer_id
Why not put the results on multiple rows?
SELECT genre_id, COUNT(*)
FROM inventory i INNER JOIN
transactions t
ON i.title_id = t.inventory_id
WHERE t.customer_id = 1 and i.genre_id IN (1, 2, 3)
GROUP BY genre_id;
So basically I have 3 tables: student, class, and enrollment.
CREATE TABLE class
(`class_name` varchar(13), `class_id` int primary key)
;
INSERT INTO class
(`class_name`, `class_id`)
VALUES
('math', 5697),
('science', 5768),
('computer', 6315),
('physical-ed', 6422),
('music', 7528),
('art', 7604),
('jrotc', 8797),
('culinary-arts', 8069)
;
CREATE TABLE student
(`student_fname` varchar(8), `student_id` varchar(11) primary key)
;
INSERT INTO student
(`student_fname`, `student_id`)
VALUES
('james', 'Vre94b3JpXO'),
('jim', 'JzqQ2zRVNm1'),
('jenny', 'xgqv9P42eYL'),
('kyle', 'QLNM0Wbyqk0'),
('kimberly', 'P2egAddWN0Q'),
('kayla', 'EGNDjWAreAy'),
('noah', 'bPeOyMMONGr'),
('nataly', '9Op53GGmqk5')
;
create table enrollment (
`no` int(10),
`student_id` varchar(11),
`class_id` int,
`semester` varchar(20),
primary key (`student_id`, `class_id`, `semester`),
foreign key (`student_id`) references student (`student_id`),
foreign key (`class_id`) references class (`class_id`)
);
insert into enrollment values
(1, 'Vre94b3JpXO', 5697, 'Fall 2015'),
(2,'JzqQ2zRVNm1', 5697, 'Fall 2015'),
(3, 'xgqv9P42eYL', 5697, 'Fall 2015'),
(4, 'JzqQ2zRVNm1', 8069, 'Fall 2014'),
(5, 'xgqv9P42eYL', 8069, 'Fall 2014');
If I follow the query:
select * from student s
join enrollment e on s.student_id = e.student_id
join class c on c.class_id = e.class_id
I would get something like this:
How could I remove the redundant column like student_id and class_id?
This question is extended from the page:
Table structure - Link one student with multiple classes id
and demo
I have been using the joining method but I couldn't get what I wanted, thanks for your help.
To answer this question, it might be nice to review some basics :
SELECT *
This * is to display all the columns from the table(s) you have selected
If you want to display only some columns, you have to specificly name it :
SELECT class_name, ...
But if you have some tables with the same column name, you have to specify the table name or alias :
SELECT c.class_name
FROM mytable t
INNER JOIN class c ON c.id_table = t.id
Just specify the columns you want to see.
select s.student_fname, s.student_id,
e.no, e.class_id, e.semester,
c.class_name,
from
student s join enrollment e
on s.student_id = e.student_id
join class c
on c.class_id = e.class_id ;
Something like this:
SELECT s.*
,e.no
,e.class_id
,e.semester
,c.class_name
FROM student s
INNER JOIN enrollment e ON s.student_id = e.student_id
INNER JOIN class c ON c.class_id = e.class_id
In your select you can specify each column you'd like and thus what order.
SELECT e.no
,e.class_id
If you want all columns from a table you can do that table dot star like:
SELECT s.*
As you already have in the existing query you can simply do star to get all the columns:
SELECT *
Here is a good place to start for some basic SELECT tricks: https://www.techrepublic.com/article/sql-basics-select-statement-options/
On an aside, it can be helpful to use a site like: http://poorsql.com/ to help with your SQL formatting.
I want to get data from two tables in my DB. Here's what my tables might look like:
subject_code: semester, subjectcode, subjectname
markmanagment: subjectcode, semester, marks, rollno
i want to select rollno value=1 and semester value=1 and its corresponding values of marks and subject code from table markmanagment and for the same value of semester and subject code i want the subjectname from subject_code
This is a very basic join. Use an INNER JOIN to see only the results that have records in both tables - I used the subject code in the ON statement but you could also use semester here. Then specify your other conditions in the WHERE clause. In your SELECT statement, specify the columns you want to see returned by listing them in the following format: tablename.columnname. I use * here to return all columns.
SELECT *
FROM subject_code sc
INNER JOIN markmanagement mm ON sc.subjectcode = mm.subjectcode
WHERE sc.semester = mm.semester
AND sc.semester = 1
AND mm.rollno = 1
You should do a join table (Inner - Right - Left or Full, depending on your table).
Like :
SELECT * FROM subject_code
INNER JOIN markmanagment
ON subject_code.subjectcode = markmanagment.subjectcode;
WHERE markmanagment.rollno = 1 AND subject_code.semester = 1
You can specify multiple conditions in the on part of a join. For example:
select *
from markmanagement mm
join subject_code sc
on mm.subjectcode = sc.subjectcode
and mm.semester = sc.semester
where mm.semester = 1
and mm.rollno = 1
Hoping, i understood your problem correctly.
Tried to create same problem.
Sqlfiddle link - http://sqlfiddle.com/#!9/5a074b/2/0
create table subject_code
(
semester int,
subjectcode varchar(100),
subjectname varchar(100)
);
insert into subject_code values(1,'S01','subject1');
insert into subject_code values(1,'S02','subject2');
insert into subject_code values(2,'S01','subject1');
create table markmanagment
(
subjectcode varchar(100),
semester int,
marks int ,
rollno int
);
insert into markmanagment values('S01',1,75,1);
insert into markmanagment values('S02',1,80,1);
insert into markmanagment values('S01',2,85,1);
I think below query will help
select b.marks , b.subjectcode , a.subjectname
from subject_code a, markmanagment b
where a.semester = b.semester
and a.subjectcode = b.subjectcode
and a.semester = 1
and b.rollno = 1;
list employees names (Ename) who have both 49008 zip code customers and 49009 zip code customers.
I am struggling to answer the above query based on the above tables.
If the names match between tables assume constraint.
I can filter down to name and zip easily by left joins and group by but struggle after that, I don't know the proper where or having statement. I am assuming it could be done better by a sub query but not sure. Ideally, a single query.
Please and thank you.
1) Create and insert statements for example data:
Create table Employees (EM_Eno INT NOT NULL, EM_Ename VARCHAR(50), EM_Hire_Date DATE, PRIMARY KEY(EM_Eno));
Create table Customers (Customers_Cno INT NOT NULL, Customers_Cname VARCHAR(50), Customers_Street VARCHAR(50), Customers_Zip INT, Customers_Phone INT, primary key(Customers_Cno));
Create table Orders (Orders_Ono INT NOT NULL, Orders_Cno INT, Orders_Eno INT, Orders_Received DATE, Orders_Shipped DATE, primary key(Orders_Ono));
insert into Orders values
( 1,301,501,20161010,20161011);
( 2,302,501,20161011,20161012);
( 3,303,502,20161110,20161111);
( 4,304,502,20161110,20161112);
( 5,305,502,20161110,20161113);
( 6,306,503,20161112,20161114);
( 7,307,501,20161112,20161113);
( 8,308,503,20161112,20161115);
( 9,309,503,20161115,20161120);
(10,300,501,20161112,20161113);
insert into Customers values
(300,'Bryan','100 street',49009,1234567890),
(301,'Ryan','101 street',49008,1234567890),
(302,'Nick','102 street',49009,1234567890),
(303,'Nicholas','103 street',49009,1234567890),
(304,'Alexa','104 street',49009,1234567890),
(305,'Tori','105 street',49008,1234567890),
(306,'Scarlet','106 street',49008,1234567890),
(307,'Heather','100 street',49009,1234567890),
(308,'Amanda','107 street',49008,1234567890),
(309,'James','108 street',49008,1234567890);
insert into Employees values
(501,'Robert',20041010),
(502,'Sam',20050110),
(503,'Brandy',20050710);
2) Ideal end result is answering the query "list employees (names) who have both 49008-zipcode customers and 49009-zipcode customers."
3) Best Attempt thus far:
select Employees.EM_Ename
, Customers.Customers_Zip
from Employees
left
join Orders
on Employees.EM_Eno = Orders.Orders_Eno
left
join Customers
on Orders.Orders_Cno = Customers.Customers_Cno
group
by Employees.EM_Ename
, Customers.Customers_Zip;
The table names are altered slightly in the rextest, because other tables already exist there with the same name...
SELECT e.*
FROM tbl_employees e
JOIN tbl_orders o
ON o.orders_eno = e.em_eno
JOIN tbl_customers c
ON c.Customers_Cno = o.Orders_Cno
WHERE c.Customers_Zip IN(49008,49009)
GROUP
BY e.em_eno
HAVING COUNT(DISTINCT customers_zip) = 2;
http://rextester.com/HCNLU51847
This should be what you want:
select Min(e.Ename)
from #Employees e
join #Orders o on o.Eno = e.Eno
join #Customers c on c.Cno = o.Cno
join #Orders o2 on o2.Eno = e.Eno
join #Customers c2 on c2.Cno = o2.Cno
where o.Ono !=o2.Ono--c.Cno != c2.Cno and
and c.Zip = 49008 and c2.Zip = 49009
group by e.Ename,c.Zip
order by e.Ename
As you can see if you wanted more than those two the self joins become longer.
I have old tables
Items(vendorId-FK, ManufacturerId (IS NOT FK)),
Vendors(PK- VendorId int),
Manufacturer(PK-ManufacturerId int)
Need to transfer data to new DB and it works on transferring data from vendor, but from Manufacturer it transfer only 30000 (where oldManufacturerId is not null), and other 5000 is not transferred. Any ideas what I'm doing wrong?
New Table Manufacturer
( OldManufacturerID int,
newManufacturerId Uniqueidentifier default newid(),
ManufacturerName varchar (100),
)
New Table Items
( ...
ItemDescription,
ManufacturerId uniqueidentifier,
VendorId uniqueidentifier
)
INSERT INTO dbo.Item
( ...
ItemDescription,
ManufacturerId ,
VendorId
)
SELECT
...
itemDescription,
m.ManufacturerId ,
v.VendorId
FROM OldSqlDatabase.dbo.tbl_Items i
JOIN NewSqlDatabase.dbo.Vendor v ON ISNULL(i.vendor_id, '') = ISNULL(v.SourceVendorID, '')
JOIN NewSqlDatabase.dbo.Manufacturer m ON ISNULL(i.manufacturer_id, '') = ISNULL(m.SourceManufacturerID, '')
I just transfered a data since this table didn't have any relationships, new manufactureId has default newid(), and this new id i want to use in the new item table
INSERT INTO dbo.Manufacturer
( OldManufacturerID ,
ManufacturerName ,
)
SELECT
manufacturer_id ,
manufacturer_name ,
FROM oldManufacture
You likely need to use a LEFT JOIN the get records where there a no values (null values) on which to join. The LEFT JOIN will allow you to select all records from the first table being specified in the join, even if there are no matching records available in the second table in the join.
This would also allow you to get rid of that ISNULL() stuff in the join definitions as well. Those would perform very poorly, as they would not be able to use indexes.
I would suggest something like:
INSERT INTO dbo.Item
( ...
ItemDescription,
ManufacturerId ,
VendorId
)
SELECT
...
itemDescription,
m.ManufacturerId ,
v.VendorId
FROM OldSqlDatabase.dbo.tbl_Items i
LEFT JOIN NewSqlDatabase.dbo.Vendor v
ON i.vendor_id = v.SourceVendorID
LEFT JOIN NewSqlDatabase.dbo.Manufacturer m
ON i.manufacturer_id = m.SourceManufacturerID