-- 10/14
tee 2024_10_14_sql_log.txt
use toyu

-- CP
SELECT s.*, e.*
FROM student AS S CROSS JOIN enroll AS e;

-- theta join
SELECT s.*, e.*
FROM student AS S CROSS JOIN enroll AS e  ON (ach >= 70 and grade = 'A');

-- Equi-join: common attribute: stuId.
SELECT s.*, e.*
FROM student AS S CROSS JOIN enroll AS e USING (stuId);


SELECT *
FROM student AS S NATURAL JOIN enroll AS e;


-- 10/7
tee 2024_10_7_sql_log.txt
use toyu

SELECT DISTINCT s.major, s.stuId,
    CONCAT(s.fname, ' ', s.lname) AS student
FROM student AS s
WHERE s.major IN ('CSCI', 'CINF', 'ITEC');


SELECT DISTINCT 'ready to go in 4 minutes.', s.major, COUNT(s.stuId) AS numStudent, 
    AVG(s.ach) AS `average ach` -- group functions, group by columns, constants
FROM student AS s
WHERE s.major IN ('CSCI', 'CINF', 'ITEC')
GROUP BY s.major;


GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | expr}
                 [ASC | DESC] [,col_name ...]]
             [SEPARATOR str_val])

SELECT DISTINCT 'ready to go in 4 minutes.', s.major, COUNT(s.stuId) AS numStudent, 
    AVG(s.ach) AS `average ach`,
    GROUP_CONCAT(CONCAT(s.fname, ' ', s.lname) ORDER BY s.lname ASC, s.fname ASC SEPARATOR "; ") AS students -- group functions, group by columns, constants
FROM student AS s
WHERE s.major IN ('CSCI', 'CINF', 'ITEC')
GROUP BY s.major;

SELECT DISTINCT 'ready to go in 4 minutes.', s.major, COUNT(s.stuId) AS numStudent, 
    AVG(s.ach) AS `average ach`,
    GROUP_CONCAT(CONCAT(s.fname, ' ', s.lname) ORDER BY s.lname ASC, s.fname ASC SEPARATOR "; ") AS students -- group functions, group by columns, constants
FROM student AS s
WHERE s.major IN ('CSCI', 'CINF', 'ITEC')
GROUP BY s.major
HAVING `average ach` >= 40;

SELECT DISTINCT 'ready to go in 4 minutes.', s.major, COUNT(s.stuId) AS numStudent, 
    AVG(s.ach) AS `average ach`,
    GROUP_CONCAT(CONCAT(s.fname, ' ', s.lname) ORDER BY s.lname ASC, s.fname ASC SEPARATOR "; ") AS students -- group functions, group by columns, constants
FROM student AS s
WHERE s.major IN ('CSCI', 'CINF', 'ITEC')
AND AVG(s.ach) >= 40 -- no group function here.
GROUP BY s.major;

ERROR 1111 (HY000): Invalid use of group function


SELECT DISTINCT 'ready to go in 4 minutes.', s.major, COUNT(s.stuId) AS numStudent, 
    AVG(s.ach) AS `average ach`,
    GROUP_CONCAT(CONCAT(s.fname, ' ', s.lname) ORDER BY s.lname ASC, s.fname ASC SEPARATOR "; ") AS students -- group functions, group by columns, constants
FROM student AS s
GROUP BY s.major
HAVING s.minor IN ('CSCI', 'CINF', 'ITEC')
AND `average ach` >= 40;
ERROR 1054 (42S22): Unknown column 's.minor' in 'having clause'

[2] Can you write a query to generate the following output?
+----------+------------------------------+------------+----------+----------+
| deptCode | deptName                     | numFaculty | numMajor | numMinor |
+----------+------------------------------+------------+----------+----------+
| ACCT     | Accounting                   |          1 |        0 |        0 |
| ARTS     | Arts                         |          1 |        2 |        0 |
| CINF     | Computer Information Systems |          2 |        2 |        3 |
| CSCI     | Computer Science             |          4 |        3 |        1 |
| ENGL     | English                      |          1 |        0 |        2 |
| ITEC     | Information Technology       |          2 |        2 |        2 |
| MATH     | Mathematics                  |          0 |        0 |        0 |
+----------+------------------------------+------------+----------+----------+
7 rows in set (0.00 sec)

-- [2a] columns 1 and 4.

SELECT DISTINCT s.major, COUNT(s.stuId) AS numMajor 
FROM student AS s
GROUP BY s.major;

SELECT DISTINCT s.major, COUNT(s.stuId) AS numMajor 
FROM department AS d INNER JOIN student AS s ON (d.deptCode = s.major)
GROUP BY s.major;

SELECT DISTINCT s.major, COUNT(s.stuId) AS numMajor 
FROM department AS d LEFT JOIN student AS s ON (d.deptCode = s.major)
GROUP BY s.major;

SELECT DISTINCT d.deptCode, COUNT(s.stuId) AS numMajor 
FROM department AS d LEFT JOIN student AS s ON (d.deptCode = s.major)
GROUP BY d.deptCode;

-- [2b] columns 1 and 5.
SELECT DISTINCT d.deptCode, COUNT(s.stuId) AS numMinor 
FROM department AS d LEFT JOIN student AS s ON (d.deptCode = s.minor)
GROUP BY d.deptCode;

-- [2c] columns 1 and 3.
SELECT DISTINCT d.deptCode, COUNT(f.facId) AS numFaculty 
FROM department AS d LEFT JOIN faculty AS f ON (d.deptCode = f.deptCode)
GROUP BY d.deptCode;

-- [2]
WITH t1 AS
(SELECT DISTINCT d.deptCode, COUNT(f.facId) AS numFaculty 
FROM department AS d LEFT JOIN faculty AS f ON (d.deptCode = f.deptCode)
GROUP BY d.deptCode),
t2 AS
(SELECT DISTINCT d.deptCode, COUNT(s.stuId) AS numMajor 
FROM department AS d LEFT JOIN student AS s ON (d.deptCode = s.major)
GROUP BY d.deptCode),
t3 AS
(SELECT DISTINCT d.deptCode, COUNT(s.stuId) AS numMinor 
FROM department AS d LEFT JOIN student AS s ON (d.deptCode = s.minor)
GROUP BY d.deptCode)
SELECT d.deptCode, d.deptName, t1.numFaculty, t2.numMajor, t3.numMinor
FROM department AS d INNER JOIN t1 USING (deptCode)
    INNER JOIN t2 USING (deptCode)
    INNER JOIN t3 USING (deptCode);
    
    
WITH temp AS
(SELECT DISTINCT sc.schoolName AS college, d.deptName AS department,
   COUNT(s.stuId) As deptMajor
FROM school AS sc INNER JOIN department AS d ON (sc.schoolCode = d.schoolCode)
   LEFT JOIN student AS s ON (s.major = d.deptCode)
GROUP BY college, department)
SELECT temp.college, temp.department,
   temp.deptMajor AS `major in department`,
   SUM(deptMajor) OVER(PARTITION BY college) AS `major in college`,
   SUM(deptMajor) OVER() AS `major in university`
FROM temp;  




-- 10/2
SELECT stuId
FROM enroll;


SELECT DISTINCT stuId
FROM enroll;

SELECT DISTINCT f.facId, f.lname
FROM faculty AS f
WHERE rank = 'Professor';

SELECT DISTINCT f.facId, f.lname
WHERE rank = 'Professor'
FROM faculty AS f;



DROP SCHEMA IF EXISTS tinker;
CREATE SCHEMA tinker;
USE tinker;

CREATE TABLE s2  -- creation + population.
SELECT * FROM toyu.student;

SELECT *
FROM s2;

CREATE TEMPORARY TABLE s3
SELECT * FROM toyu.student;

SELECT *
FROM s3;

-- CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
 --   { LIKE old_tbl_name | (LIKE old_tbl_name) }
CREATE TABLE s4 LIKE toyu.student; -- creation of table

SELECT *
FROM s4;

INSERT INTO s4  -- population.
SELECT * FROM toyu.student;

SELECT *
FROM s4;

SHOW TABLES;

-- Note that keys and constraints of student are missing in s2 and S3.
DESC toyu.student;
DESC s2;
DESC s4;

DESC s3;

DROP TABLE s2;
DROP TABLE s3;
DROP TABLE s4;

SHOW TABLES;

DROP SCHEMA IF EXISTS tinker;

UPDATE [LOW_PRIORITY] [IGNORE] table_reference
    SET assignment_list
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]
    
UPDATE Student
SET major = 'ITEC'
WHERE StuId = 100000;

UPDATE Student
SET major = 'CSCI';

-- student with credits in a range.
SELECT DISTINCT *
FROM Student
WHERE ach BETWEEN 30 AND 70;

SELECT DISTINCT *
FROM Student
WHERE ach BETWEEN 35 AND 66;


-- student with credits in a range.
SELECT DISTINCT *
FROM Student
WHERE ach>= 30 AND ach <= 70;

SELECT DISTINCT s.fname, s.lname, c.classId, e.grade
FROM student AS s, enroll AS e, class AS c
WHERE s.stuId = e.stuId -- Join condition
AND e.classId = c.classId -- Join condition
AND c.semester = 'Fall' -- problem condition
AND c.year = 2019; -- problem condition

SELECT DISTINCT s.fname, s.lname, c.classId, e.grade
FROM student AS s INNER JOIN enroll e ON (s.stuId = e.stuId) -- Join condition
    INNER JOIN class AS c ON (e.classId = c.classId) -- Join condition
WHERE c.semester = 'Fall' -- Problem condition
AND c.year = 2019; -- Problem condition

-- List the names of the students with their minors (in full name).
-- Student with no department not listed.
SELECT DISTINCT CONCAT(s.fname, ' ', s.lname) AS student,
    d.deptName AS `minor department`
FROM student AS s INNER JOIN department AS d ON (s.minor = d.deptCode);


SELECT DISTINCT CONCAT(s.fname, ' ', s.lname) AS student,
    d.deptName AS `minor department`
FROM student AS s LEFT JOIN department AS d ON (s.minor = d.deptCode);


SELECT DISTINCT CONCAT(s.fname, ' ', s.lname) AS student,
    IFNULL(d.deptName, 'Undeclared') AS `minor department`
FROM student AS s LEFT JOIN department AS d ON (s.minor = d.deptCode);

-- subqueries in the WHERE course
-- students not enrolled in any class.
SELECT DISTINCT *
FROM student AS s
WHERE s.stuId NOT IN (SELECT DISTINCT e.stuID FROM enroll AS e);

-- student with the maximum number of ach.
SELECT DISTINCT MAX(ach) -- group function
FROM student;


-- CTE
WITH  t1 AS
   (SELECT MAX(ach) AS max FROM student)
SELECT s.stuId,
   s.ach AS `ach credits`,
   t1.max - s.ach AS `diff from max credits of all`
FROM student AS s, t1
ORDER BY `ach credits` DESC;

-- student within 60 credits of the maximum number of ach any student may have.
SELECT DISTINCT s.stuId,
   CONCAT(s.fname, ' ', s.lname) AS student,
   s.ach AS credits
FROM student AS s
WHERE s.ach + 60 >=
   (SELECT DISTINCT MAX(ach) FROM student); -- implicit type converstion: a table -> a number: 125

-- subqueries as derived tables.
SELECT DISTINCT s.stuId,
   CONCAT(s.fname, ' ', s.lname) AS student,
   s.ach AS credits
FROM student AS s INNER JOIN
   (SELECT DISTINCT MAX(ach) AS max FROM student) AS m -- an alias is required.
WHERE s.ach + 60 >= m.max;

-- CTE
WITH m AS -- step [1]
(SELECT DISTINCT MAX(ach) AS max FROM student)
SELECT DISTINCT s.stuId,
   CONCAT(s.fname, ' ', s.lname) AS student,
   s.ach AS credits
FROM student AS s INNER JOIN m 
WHERE s.ach + 60 >= m.max;


-- CTE
WITH  t1 AS
   (SELECT MAX(ach) AS max FROM student)
SELECT s.stuId,
   s.ach AS `ach credits`,
   t1.max - s.ach AS `diff from max credits of all`
FROM student AS s, t1
ORDER BY `ach credits` DESC;

-- CTE solution
WITH t1 AS -- Common table scope: just the current SQL statement.
    -- scope should be as small as possible.
   (SELECT MAX(ach) AS max FROM student),
t2 AS
   (SELECT s.stuId,
      s.ach AS `ach credits`,
      t1.max - s.ach AS diff,
      s.major
    FROM student AS s, t1)
SELECT t2.stuId, t2.`ach credits`,
   t2.diff AS `diff from max credits of all`,
   d.deptName AS department
FROM t2 LEFT JOIN department d ON (t2.major = d.deptCode)
ORDER BY t2.`ach credits` DESC;
-- t1 and t2 no longer defined.

-- temporary tables;
-- scope: client session
CREATE TEMPORARY TABLE tt1 AS
SELECT MAX(ach) AS max FROM student;

SELECT * FROM tt1;

CREATE TEMPORARY TABLE tt2 AS
SELECT s.stuId,
      s.ach AS `ach credits`,
      tt1.max - s.ach AS diff,
      s.major
FROM student AS s, tt1;

SELECT * FROM tt2;

SELECT tt2.stuId, tt2.`ach credits`,
   tt2.diff AS `diff from max credits of all`,
   d.deptName AS department
FROM tt2 LEFT JOIN department d ON (tt2.major = d.deptCode)
ORDER BY tt2.`ach credits` DESC;

DROP SCHEMA IF EXISTS CTEtinker;

CREATE SCHEMA CTETinker;
USE SCHEMA CTEtinker;
CREATE OR REPLACE TABLE Employee (
    EmpId CHAR(7) NOT NULL,
    SupervisorEmpId CHAR(7) NULL,
    CONSTRAINT Emp_EmpId_pk PRIMARY KEY (EmpId),
    CONSTRAINT Emp_SupervisorEmpId_fk FOREIGN KEY (SupervisorEmpId)
        REFERENCES Employee(EmpId)
);

INSERT INTO Employee(EmpId, SupervisorEmpId) VALUES
   ('E3', null);
INSERT INTO Employee(EmpId, SupervisorEmpId) VALUES
   ('E15', 'E3');
INSERT INTO Employee(EmpId, SupervisorEmpId) VALUES
   ('E50', 'E15');
INSERT INTO Employee(EmpId, SupervisorEmpId) VALUES
   ('E75', 'E50');
INSERT INTO Employee(EmpId, SupervisorEmpId) VALUES
   ('E100', 'E75');
INSERT INTO Employee(EmpId, SupervisorEmpId) VALUES
   ('E102', 'E75');
INSERT INTO Employee(EmpId, SupervisorEmpId) VALUES
   ('E70', 'E50');
INSERT INTO Employee(EmpId, SupervisorEmpId) VALUES
   ('E103', 'E70');
  
SELECT * FROM Employee;

-- supervisor of 'E100'
SELECT DISTINCT SupervisorEmpId
FROM Employee
WHERE EmpId = 'E100';

-- All (direct/indirect supervisor of E100: E75, E50, E15, E3.
WITH RECURSIVE Super(SEId) AS
(  SELECT SupervisorEmpId AS SEId FROM Employee AS e WHERE e.EmpId = 'E100' -- initial condition/action
   -- init: Super: E75
   UNION ALL -- union all: add rows created by the recursive action to the result, table Super.
   
   SELECT e.SupervisorEmpId AS SEId -- recursive action
      FROM Employee AS e INNER JOIN Super
      WHERE e.EmpId = Super.SEId
      AND e.SupervisorEmpId IS NOT NULL -- negation of exit condition.
      -- exit condition: when the recursive action returns an empty table.
)
SELECT *
FROM Super;


SELECT DISTINCT s.major, s.stuId, s.ach
FROM student AS s
WHERE s.major IN ('CSCI', 'CINF', 'ITEC');

-- Bad meaning but MySQL allows it.
SELECT DISTINCT s.major, s.stuId, s.ach
FROM student AS s
WHERE s.major IN ('CSCI', 'CINF', 'ITEC')
GROUP BY s.major;

SELECT DISTINCT 'ready to go in 4 minutes.', s.major, COUNT(s.stuId) AS numStudent, 
    AVG(s.ach) AS `average ach` -- group functions, group by columns, constants
FROM student AS s
WHERE s.major IN ('CSCI', 'CINF', 'ITEC')
GROUP BY s.major;