Discussion 1
Intro, SQL
Agenda
Welcome!
Course website: http://www.cs186berkeley.net/
Projects are involved coding assignments
Vitamins are required weekly quizzes that keep you up to date with lectures
Midterm 1 will be on 10/1 from 8-10PM
Midterm 2 will be on 11/7 from 7-9PM (unconfirmed)
Accounts
EdStem: https://edstem.org/us/courses/62108/discussion/5190573
Gradescope: https://www.gradescope.com/courses/816103
GitHub: See Project 0 for GitHub Classroom setup
Email cs186@berkeley.edu if you have any issues
Questions?
SQL
SQL for single tables queries
SELECT [DISTINCT] <column list>�FROM <table1>�[WHERE <predicate>]�[GROUP BY <column list>]�[HAVING <predicate>]�[ORDER BY <column list> [DESC/ASC]]�[LIMIT <amount>];
Logical Processing Order
Logical Processing Order
a | b |
1 | 0 |
2 | 1 |
3 | 0 |
4 | 1 |
5 | 0 |
6 | 1 |
7 | 2 |
8 | 3 |
test_table
�FROM test_table�
Take data FROM test_table.
Logical Processing Order
a | b |
1 | 0 |
2 | 1 |
3 | 0 |
4 | 1 |
5 | 0 |
6 | 1 |
7 | 2 |
8 | 3 |
a | b |
3 | 0 |
4 | 1 |
5 | 0 |
6 | 1 |
7 | 2 |
8 | 3 |
test_table
�FROM test_table�WHERE a > 2�
Take data FROM test_table and keep rows WHERE a > 2.
Logical Processing Order
�FROM test_table�WHERE a > 2�GROUP BY b�
a | b |
3 | 0 |
4 | 1 |
5 | 0 |
6 | 1 |
7 | 2 |
8 | 3 |
We GROUP BY b, but there may be multiple values of a per group, so we can’t use a directly anymore. We can, however, use it with aggregate functions (MIN, MAX, SUM, AVERAGE, COUNT).
Using aggregate functions without a GROUP BY clause = everything in one group.
a | b |
3 | 0 |
5 | 0 |
4 | 1 |
6 | 1 |
7 | 2 |
8 | 3 |
Logical Processing Order
�FROM test_table�WHERE a > 2�GROUP BY b
HAVING COUNT(*) >= 2�
Throw away groups that have fewer than 2 rows in them.
Note: COUNT(*) includes NULL values, and COUNT(column) does not include null values.
a | b |
3 | 0 |
5 | 0 |
4 | 1 |
6 | 1 |
7 | 2 |
8 | 3 |
a | b |
3 | 0 |
5 | 0 |
4 | 1 |
6 | 1 |
Logical Processing Order
c |
0 |
1 |
SELECT b AS c�FROM test_table�WHERE a > 2�GROUP BY b
HAVING COUNT(*) >= 2�
We use an alias here: b AS c selects b, but then calls it c afterwards. We can use this alias in any step after this one (so not in SELECT, WHERE, GROUP BY, HAVING).
a | b |
3 | 0 |
5 | 0 |
4 | 1 |
6 | 1 |
Logical Processing Order
c |
0 |
1 |
SELECT DISTINCT b AS c�FROM test_table�WHERE a > 2�GROUP BY b
HAVING COUNT(*) >= 2�
There are no duplicate rows here so DISTINCT isn’t necessary, but if there were any, DISTINCT would remove them. Duplicates are removed by exact match on the entire row.
c |
0 |
1 |
Logical Processing Order
c |
1 |
0 |
SELECT DISTINCT b AS c�FROM test_table�WHERE a > 2�GROUP BY b
HAVING COUNT(*) >= 2�ORDER BY c DESC
c |
0 |
1 |
Sort the output by the columns (just c here) (numerically for integers, lexicographically for strings) in either ASCending (low to high) or DESCending (high to low) order. Default is ASC.
Note: order of output is not guaranteed unless you have an ORDER BY clause.
Logical Processing Order
c |
1 |
SELECT DISTINCT b AS c�FROM test_table�WHERE a > 2�GROUP BY b
HAVING COUNT(*) >= 2�ORDER BY c DESC
LIMIT 1
c |
1 |
0 |
Return just the first row.
A Note On GROUP BY
Dept | Course | Capacity |
CS | 186 | 715 |
CS | 161 | 485 |
EE | 16B | 580 |
EE | 105 | 40 |
DATA | 100 | 1375 |
Dept | Course | Capacity |
CS | 186 | 715 |
CS | 161 | 485 |
EE | 16B | 580 |
EE | 105 | 40 |
DATA | 100 | 1375 |
A Note On GROUP BY
Dept | Course | Capacity |
CS | 186 | 715 |
CS | 161 | 485 |
EE | 16B | 580 |
EE | 105 | 40 |
DATA | 100 | 1375 |
SELECT Dept, Course �FROM Classes GROUP BY Dept;
Dept | Course |
CS | ? |
EE | ? |
DATA | ? |
Are the following valid?
NO
SELECT Dept, SUM(Capacity) FROM Classes GROUP BY Dept;
Dept | SUM(Cap.) |
CS | 1200 |
EE | 620 |
DATA | 1375 |
YES
The Group By Rules
Given the table Students(sid, age, gpa, name, major), which of the following are valid?
SELECT age�FROM Students
GROUP BY major;
SELECT age�FROM Students
GROUP BY major, age;
SELECT MAX(age)�FROM Students
GROUP BY major;
SELECT age, MIN(gpa)�FROM Students
GROUP BY name;
NO
YES
YES
NO
String Comparison
LIKE: following expression follows SQL specified format
Examples:
~ : following expression follows regex format
Examples:
Note: ~ cannot be used in SQLite (which Project 1 will be using)
Practice: Single-Table Queries
Question 1
Find the names of the 5 songs that spent the least weeks in the top 40, ordered from least to most. Break ties by song name in alphabetical order.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
Question 1
Find the names of the 5 songs that spent the least weeks in the top 40, ordered from least to most. Break ties by song name in alphabetical order.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT song_name
FROM Songs
ORDER BY weeks_in_top_40 ASC, song_name ASC
LIMIT 5
Question 2
Find the name and first year active of every artist whose name starts with the letter ‘B’.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
Question 2
Find the name and first year active of every artist whose name starts with the letter ‘B’.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT artist_name, first_yr_active�FROM artists�WHERE artist_name LIKE 'B%'
Question 2
Find the name and first year active of every artist whose name starts with the letter ‘B’.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT artist_name, first_yr_active�FROM artists�WHERE artist_name ~ '^B.*'
Question 3
Find the total number of albums released per genre.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
Question 3
Find the total number of albums released per genre.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT genre, COUNT(album_id)
FROM Albums
GROUP BY genre;
Question 4
Find the total number of albums released per genre. Don’t include genres with a count less than 10.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
Question 4
Find the total number of albums released per genre. Don’t include genres with a count less than 10.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT genre, COUNT(*)
FROM Albums
GROUP BY genre
HAVING COUNT(*) >= 10;
Question 5
Find the genre for which the most albums were released in the year 2000. Assume there are no ties.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
Question 5
Find the most popular album genre that is released in the year 2000. Assume there are no ties.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT genre
FROM Albums
WHERE yr_released = 2000
GROUP BY genre
ORDER BY COUNT(*) DESC
LIMIT 1;
SQL Joins
Join Variants
SELECT * FROM
T1 INNER JOIN T2
ON T1.a = T2.a;
Join Condition
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Kimberly | 18 | Freshman |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Kimberly | 18 | Freshman |
Result
Inner Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages INNER JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Kimberly | 18 | Freshman |
Result
Left Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages LEFT JOIN standing
ON ages.Name = standing.Name;
Left Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages LEFT JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Kimberly | 18 | Freshman |
Lakshya | 22 | null |
Result
Right Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages RIGHT JOIN standing
ON ages.Name = standing.Name;
Right Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages RIGHT JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Kimberly | 18 | Freshman |
null | null | Senior |
Result
Full Outer Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages FULL JOIN standing
ON ages.Name = standing.Name;
Full Outer Join, Example
Name | Age |
Brian | 20 |
Lakshya | 22 |
Kimberly | 22 |
Kimberly | 18 |
Ages
Name | Year |
Brian | Junior |
Kimberly | Freshman |
Ben | Senior |
Standing
SELECT ages.Name, ages.Age, standing.Year
FROM ages FULL JOIN standing
ON ages.Name = standing.Name;
Name | Age | Year |
Brian | 20 | Junior |
Kimberly | 22 | Freshman |
Kimberly | 18 | Freshman |
null | null | Senior |
Lakshya | 22 | null |
Result
Practice: Multi-Table Joins
Question 1
Find the names of all artists who released a ‘country’ genre album in 2020.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
Question 1
Find the names of all artists who released a ‘country’ genre album in 2020.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT artist_name
FROM Artists AS A
INNER JOIN Albums AS B
ON A.artist_id = B.artist_id
WHERE genre = ‘country’ AND yr_released = 2020
GROUP BY A.artist_id, artist_name;
Question 2
Find the name of the album with the song that spend the most weeks in the top 40. Assume there is only one such song.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
Question 2
Find the name of the album with the song that spend the most weeks in the top 40. Assume there is only one such song.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT album_name
FROM Albums AS A INNER JOIN Songs AS S �ON A.album_id = S.album_id
ORDER BY weeks_in_top_40 DESC LIMIT 1;
Question 3
Find the artist name and the most weeks one of their songs spent in the top 40 for each artist. Include artists that have not released an album.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
Question 3
Find the artist name and the most weeks one of their songs spent in the top 40 for each artist. Include artists that have not released an album.
Tables
Songs �(song_id, song_name, album_id, weeks_in_top_40)
Artists �(artist_id, artist_name, first_yr_active)
Albums �(album_id, album_name, artist_id, yr_released, genre)
SELECT artist_name, MAX(weeks_in_top_40)
FROM Artists LEFT JOIN
(Songs INNER JOIN Albums ON Songs.album_id = Albums.album_id)
ON Artists.artist_id = Albums.artist_id
GROUP BY Artists.artist_id, artist_name;
Appendix (Tips and Tricks)
Attendance Link