How do I write MySQL queries? - mysql

I had to create two tables (students and grades) and then insert the values.
These are the queries-
CREATE TABLE students ( student_id INT(3) NOT NULL PRIMARY KEY AUTO_ INCREMENT,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(50) NOT NULL );
CREATE TABLE grades ( student_id INT (3) NOT NULL PRIMARY KEY AUTO_
INCREMENT,
gpa DOUBLE );'
INSERT INTO students (student_id, firstname, lastname) VALUES (‘123’,
‘Some’, ‘One’);
INSERT INTO students (student_id, firstname,lastname) VALUES (‘125’,
‘Another’, ‘One’);
INSERT INTO students (student_id, firstname,lastname) VALUES (‘167’, ‘Good’,
‘Student’);
INSERT INTO grades (student_id, gpa) VALUES (‘123’, ‘2.34);
INSERT INTO grades (student_id, gpa) VALUES (‘125’, ‘3.21’);
INSERT INTO grades (student_id, gpa) VALUES (‘167’, ‘3.86’);
So, now, if I have to use the SQL select query to find specific rows (GPA above 3.5) and have to use the LEFT and the CONCAT function to give me the name Good Student, exactly how do I do that? How do I use the LEFT and the CONCAT functions to generate rows?

I assume that by "left" you meant a left join, but that won't really be appropriate here - every student must have a GPA, and if, for some obscure reason, a certain student doesn't, then by definition he cannot have a GPA of about 3.5. To make a long story short - an inner join would be much more appropriate:
SELECT CONCAT_WS(' ', firstname, lastname)
FROM students s
JOIN grades g ON s.student_id = g.student_id
WHERE gpa > 3.5

Although the option by Mureinik is legit, and correct you don't need a left-join, you can actually think of it in reverse. Don't start with the student, but start with the grades... This is more of a mental perception, but shows how the same results can be obtained with slightly different queries
select
concat_ws( ' ', s.firstname, s.lastname ) studentName,
g.gpa
from
grades g
join students s
on g.student_id = s.student_id
where
g.gpa > 3.5
Also, best to qualify your table (or alias 'g' and 's' in this case) with the column name references to prevent ambiguity for yourself or others to look back at queries in the future.

Related

SQL: create global alias for nested SELECT to be used in another nested SELECT

Let's assume I've got a database with two tables: people which contains person's id and his/her birth year for each person and parents which contains the (parent_id, child_id) pairs to represent the relative relationships between people. To make the explanation easier let's assume each person has either 0 children or 1 child. Here is an example of the data in the database (as a set of SQL statements to create it on MySQL):
CREATE TABLE people (
id INTEGER NOT NULL AUTO_INCREMENT,
birth_year INTEGER NOT NULL,
CONSTRAINT PRIMARY KEY(id)
);
CREATE TABLE parents (
parent_id INTEGER NOT NULL,
child_id INTEGER NOT NULL,
CONSTRAINT PRIMARY KEY(parent_id,child_id)
);
-- Not creating FOREIGN KEYS, because it's just an example
INSERT INTO people (id, birth_year) VALUES (1, 1937);
INSERT INTO people (id, birth_year) VALUES (2, 1943);
INSERT INTO people (id, birth_year) VALUES (3, 1974);
INSERT INTO people (id, birth_year) VALUES (4, 2001);
INSERT INTO people (id, birth_year) VALUES (5, 2020);
INSERT INTO parents (parent_id, child_id) VALUES (1, 4);
INSERT INTO parents (parent_id, child_id) VALUES (3, 5);
Result:
Now I want to make up a query which will retrieve the id of the person, whose child was born at the earliest age of the parent (for example, if I was born in 1234 and my child was born in 1300, then my age when my child was born was 1300 - 1234 = 66 and I would like to find a person which got their child earlier than others).
I have made up some queries for it, but each of them either didn't work or had duplications or both. The one I like most is
SELECT id AS pid, -- Parent id
(SELECT child_id FROM parents WHERE parent_id=pid) AS cid -- Child id
FROM people WHERE
EXISTS(SELECT cid) -- Only selecting parents who have children (not sure this part is correct)
ORDER BY (birth_year - (SELECT birth_year FROM people WHERE id=cid)) ASC -- Order by age when they got their child
LIMIT 1;
But this one fails in MySQL with the error:
ERROR 1054 (42S22) at line 24: Unknown column 'cid' in 'field list'
How do I fix the error? Another thing I am worried about is that as a result, I will select not only the parent's id but also the id of one of his/her children. Is it possible to avoid it?
Probably there is a better way to select the data I'm looking for?
You can get the ages by using joins:
select c.*, (p.birth_year - c.birth_year) as parent_age
from parents pa join
people p
on pa.parent_id = p.id join
people c
on pa.child_id = pc.id;
To get all the rows with the minimum, use window functions:
select x.*
from (select c.*, (p.birth_year - c.birth_year) as parent_age,
min(p.birth_year - c.birth_year) over () as min_age
from parents pa join
people p
on pa.parent_id = p.id join
people c
on pa.child_id = pc.id
) x
where parent_age = min_age;

Find max of count on group by

I am having some trouble answering the following question.
For each age value that appears in the Student table, find the level value that
appears most often. For example, if there are more FR level students aged 18 than SR,
JR, or SO students aged 18, you should print the pair (18, FR).
from this data set.
create database university;
use university;
create table student(
snum decimal(9) primary key,
sname varchar(30),
major varchar(25),
level varchar(2),
age int
);
create table faculty(
fid decimal(9) primary key,
fname varchar(30),
deptid decimal(2)
);
create table class(
cname varchar(40) primary key,
meets_at varchar(20),
room varchar(10),
fid decimal(9),
foreign key(fid) references faculty(fid)
);
create table enrolled(
snum decimal(9),
cname varchar(40),
primary key(snum,cname),
foreign key(snum) references student(snum),
foreign key(cname) references class(cname)
);
insert into student values(051135593,'Maria White','English','SR',21);
insert into student values(060839453,'Charles Harris','Architecture','SR',22);
insert into student values(099354543,'Susan Martin','Law','JR',20);
insert into student values(112348546,'Joseph Thompson','Computer Science','SO',19);
insert into student values(115987938,'Christopher Garcia','Computer Science','JR',20);
insert into student values(132977562,'Angela Martinez','History','SR',20);
insert into student values(269734834,'Thomas Robinson','Psychology','SO',18);
insert into student values(280158572,'Margaret Clark','Animal Science','FR',18);
insert into student values(301221823,'Juan Rodriguez','Psychology','JR',20);
insert into student values(318548912,'Dorthy Lewis','Finance','FR',18);
insert into student values(320874981,'Daniel Lee','Electrical Engineering','FR',17);
insert into student values(322654189,'Lisa Walker','Computer Science','SO',17);
insert into student values(348121549,'Paul Hall','Computer Science','JR',18);
insert into student values(351565322,'Nancy Allen','Accounting','JR',19);
insert into student values(451519864,'Mark Young','Finance','FR',18);
insert into student values(455798411,'Luis Hernandez','Electrical Engineering','FR',17);
insert into student values(462156489,'Donald King','Mechanical Engineering','SO',19);
insert into student values(550156548,'George Wright','Education','SR',21);
insert into student values(552455318,'Ana Lopez','Computer Engineering','SR',19);
insert into student values(556784565,'Kenneth Hill','Civil Engineering','SR',21);
insert into student values(567354612,'Karen Scott','Computer Engineering','FR',18);
insert into student values(573284895,'Steven Green','Kinesiology','SO',19);
insert into student values(574489456,'Betty Adams','Economics','JR',20);
insert into student values(578875478,'Edward Baker','Veterinary Medicine','SR',21);
insert into faculty values(142519864,'Ivana Teach',20);
insert into faculty values(242518965,'James Smith',68);
insert into faculty values(141582651,'Mary Johnson',20);
insert into faculty values(011564812,'John Williams',68);
insert into faculty values(254099823,'Patricia Jones',68);
insert into faculty values(356187925,'Robert Brown',12);
insert into faculty values(489456522,'Linda Davis',20);
insert into faculty values(287321212,'Michael Miller',12);
insert into faculty values(248965255,'Barbara Wilson',12);
insert into faculty values(159542516,'William Moore',33);
insert into faculty values(090873519,'Elizabeth Taylor',11);
insert into faculty values(486512566,'David Anderson',20);
insert into faculty values(619023588,'Jennifer Thomas',11);
insert into faculty values(489221823,'Richard Jackson',33);
insert into faculty values(548977562,'Ulysses Teach',20);
insert into class values('Data Structures','MWF 10','R128',489456522);
insert into class values('Database Systems','MWF 12:30-1:45','1320 DCL',142519864);
insert into class values('Operating System Design','TuTh 12-1:20','20 AVW',489456522);
insert into class values('Archaeology of the Incas','MWF 3-4:15','R128',248965255);
insert into class values('Aviation Accident Investigation','TuTh 1-2:50','Q3',011564812);
insert into class values('Air Quality Engineering','TuTh 10:30-11:45','R15',011564812);
insert into class values('Introductory Latin','MWF 3-4:15','R12',248965255);
insert into class values('American Political Parties','TuTh 2-3:15','20 AVW',619023588);
insert into class values('Social Cognition','Tu 6:30-8:40','R15',159542516);
insert into class values('Perception','MTuWTh 3','Q3',489221823);
insert into class values('Multivariate Analysis','TuTh 2-3:15','R15',090873519);
insert into class values('Patent Law','F 1-2:50','R128',090873519);
insert into class values('Urban Economics','MWF 11','20 AVW',489221823);
insert into class values('Organic Chemistry','TuTh 12:30-1:45','R12',489221823);
insert into class values('Marketing Research','MW 10-11:15','1320 DCL',489221823);
insert into class values('Seminar in American Art','M 4','R15',489221823);
insert into class values('Orbital Mechanics','MWF 8','1320 DCL',011564812);
insert into class values('Dairy Herd Management','TuTh 12:30-1:45','R128',356187925);
insert into class values('Communication Networks','MW 9:30-10:45','20 AVW',141582651);
insert into class values('Optical Electronics','TuTh 12:30-1:45','R15',254099823);
insert into class values('Intoduction to Math','TuTh 8-9:30','R128',489221823);
insert into enrolled values(112348546,'Database Systems');
insert into enrolled values(115987938,'Database Systems');
insert into enrolled values(348121549,'Database Systems');
insert into enrolled values(322654189,'Database Systems');
insert into enrolled values(552455318,'Database Systems');
insert into enrolled values(455798411,'Operating System Design');
insert into enrolled values(552455318,'Operating System Design');
insert into enrolled values(567354612,'Operating System Design');
insert into enrolled values(112348546,'Operating System Design');
insert into enrolled values(115987938,'Operating System Design');
insert into enrolled values(322654189,'Operating System Design');
insert into enrolled values(567354612,'Data Structures');
insert into enrolled values(552455318,'Communication Networks');
insert into enrolled values(455798411,'Optical Electronics');
insert into enrolled values(301221823,'Perception');
insert into enrolled values(301221823,'Social Cognition');
insert into enrolled values(301221823,'American Political Parties');
insert into enrolled values(556784565,'Air Quality Engineering');
insert into enrolled values(099354543,'Patent Law');
insert into enrolled values(574489456,'Urban Economics');
My best attempt is correct, which is:
select age, level from (select age, level, count(level) as levelCount from student group by age, level order by age, levelCount desc) as counts group by age;
But it breaks the rules of standard sql where every selected value must be group by, which I don't do with the outer most select statement, level. I am taking advantage of MySQl's functionality to return non-aggregated data.
The question is how can I return the max of a count for each group that is created from a group by, while conforming to standard sql best practices.
select age, level, count(level) as levelCount from student group by age, level order by age, levelCount desc;
Please and thank you
This is a pain in MySQL. One way is to use variables. However, the simplest way uses group_concat()/substring_index() trick:
select age,
substring_index(group_concat(level order by levelCount desc), ',', 1) as mode_level
from (select age, level, count(level) as levelCount
from student
group by age, level
order by age, levelCount desc
) as counts
group by age;
(Statistically, what you are looking for is called the mode.)
Note: This is a trick. The intermediate space for group_concat() is -- by default -- 1,024 characters, so it could result in an out-of-space/overflow error. This limit is easily increased.

SQL: How to insert data in specific column with specific id as well

Is it possible to perform kind of that query on single table?
I have read that it could be done by multiple tables (inserting in first table by selecting that specific value from second )
INSERT INTO Customers (CustomerName, Country)
SELECT SupplierName, Country FROM Suppliers
WHERE Country='Germany';
Is it possible to perform kind of that query on single table?
Yes, it is possible:
CREATE TABLE Customers(ID INT IDENTITY(1,1),
CustomerName VARCHAR(100), Country VARCHAR(100));
INSERT INTO Customers (CustomerName, Country)
VALUES ('John', 'USA'), ('Martin','Germany');
INSERT INTO Customers (CustomerName, Country)
SELECT CustomerName, Country
FROM Customers
WHERE Country='Germany';
SELECT *
FROM Customers;
LiveDemo
Keep in mind that Table Spool is required to avoid Halloween Effect

MySQL table find queries

I am having a hard time implementing these queries. Can someone help.
Query 1: Find the names of the drivers who took at least 2 exams at the same branch.
Query 2: Find the names of the drivers whose exam scores get lower when he/she took more exams.
my code
create table branch(branch_id integer, branch_name varchar(20), branch_addr varchar(50), branch_city varchar(20), branch_phone integer);
create table driver(driver_ssn integer, driver_name varchar(20), driver_addr varchar(50), driver_city varchar(20), driver_birthdate date, driver_phone integer);
create table license(license_no integer, driver_ssn integer, license_type char, license_class integer, license_expiry date, issue_date date, branch_id integer);
create table exam(driver_ssn integer, branch_id integer, exam_date date, exam_type char, exam_score integer);
insert into branch values(10,'Main','1234 Main St.','Vancouver',5551234);
insert into branch values(20,'Richmond','23 No. 3 road','Richmond',5552331);
insert into branch values(30,'West Creek','251 creek rd.','Sechelt',5552511);
insert into branch values(40,'Blenheim','1342 W.22 Ave.','Burnaby',5551342);
insert into driver values(11111111, 'Bob Smith','111 E.11 st.', 'Vancouver', '1975-01-01',5551111);
insert into driver values(22222222, 'John Walters','222 E.22 st.', 'Burnaby', '1976-02-02',5552222);
insert into driver values(33333333, 'Troy Rops','333 W.33 ave.', 'Richmond', '1970-03-03',5553333);
insert into driver values(44444444, 'Kevin Mark','444 E.4 ave.', 'Vancouver', '1974-04-04',5554444);
insert into license values(1, 11111111,'D', 5, '1999-05-25','1997-05-25',20);
insert into license values(2, 22222222,'D', 5, '1998-08-29','1996-08-29',40);
insert into license values(3, 33333333,'L', 5, '1997-12-27','1997-06-27',20);
insert into license values(4, 44444444,'D', 5, '1999-08-30','1997-08-30',40);
insert into exam values(11111111,20, '1997-05-25', 'D',79);
insert into exam values(11111111,20, '1997-12-02', 'L',97);
insert into exam values(22222222,30, '1996-05-06', 'L',25);
insert into exam values(22222222,40, '1996-06-10', 'L',51);
insert into exam values(22222222,40, '1996-08-29', 'D',81);
insert into exam values(33333333,10, '1997-07-07', 'L',45);
insert into exam values(33333333,20, '1997-06-27', 'L',49);
insert into exam values(33333333,20, '1997-07-27', 'L',61);
insert into exam values(44444444,10, '1997-07-27', 'L',71);
insert into exam values(44444444,20, '1997-08-30', 'D',65);
My Attempt on Query 1:
select driver.driver_name
from exam, branch, driver
where driver.driver_ssn = exam.driver_ssn AND
(select exam.driver_ssn
from exam
group by exam.driver.ssn, exam.branch_id
having count(exam.branch_id) >= 2);
Well, the first query might look something like this...
SELECT something
FROM somehere d
JOIN somewhere_else e
ON e.some_other_thing = d.some_other_thing
GROUP
BY d.some_other_thing
, e.and_yet_another_thing
HAVING COUNT(*) >= 2;
Assuming question 2 means 'find the names of drivers who posess a subsequent exam score lower than a preceding one', then that might look like this...
SELECT DISTINCT d.driver_name
FROM ... d
JOIN ... preceding
ON preceding.... = d....
JOIN ... subsequent
ON subsequent.... = preceding....
AND subsequent.... > preceding....
AND subsequent.... < preceding....;
first query something like this
select d.driver_name from driver d inner join exam e on d.driver_ssn=e.driver_ssn inner join branch b on e.branch_id=b.branch_id
group by d.driver_name
having count(*)>=2

With MySQL, how do I insert into a table on condition that the value does not exist in same table?

insert into student (FirstName,AGE,CITYID) values('guna','26','1')
select * from student WHERE FirstName!='guna';
This query showing error.I can't make FirstName column as unique. Please give an idea other than this.
Thanks
INSERT INTO student ( ....)
WHERE FirstName NOT IN (SELECT FirstName FROM student)
After revision and testing:
INSERT INTO student
(FirstName, age, cityid)
SELECT
'guna','26','1'
FROM student -- any table name will do
WHERE 'guna' NOT IN
(
SELECT FirstName
FROM student
)
LIMIT 1 -- required because all rows will qualify if
-- WHERE clause is satisfied
You can add a unique index on that table which will do the same for you
ALTER TABLE student ADD UNIQUE <name_of_index>[optional] (FirstName);
EDIT:
If you cant use a unique index..
One soln i can think of is using compound statements - http://dev.mysql.com/doc/refman/5.0/en/if-statement.html