1 of 63

Discussion 1

Intro, SQL

2 of 63

Agenda

  1. Welcome!
  2. Getting started
  3. SQL

3 of 63

Welcome!

Course website: http://www.cs186berkeley.net/

Projects are involved coding assignments

  • Project 1 is released and due Thursday 9/12 at 11:59PM

Vitamins are required weekly quizzes that keep you up to date with lectures

  • Vitamin 1 due Monday 9/9 at 11:59PM
  • Vitamin 2 due Monday 9/16 at 11:59PM

Midterm 1 will be on 10/1 from 8-10PM

Midterm 2 will be on 11/7 from 7-9PM (unconfirmed)

4 of 63

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

5 of 63

Questions?

6 of 63

SQL

7 of 63

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>];

  • SQL is declarative - you describe what you want in the output, and the DBMS decides how it’s fetched.

8 of 63

Logical Processing Order

  1. FROM <table1> - which table are we drawing data from
  2. [WHERE <predicate>] - only keep rows where <predicate> is satisfied
  3. [GROUP BY <column list>] - group together rows by value of columns in <column list>
  4. [HAVING <predicate>] - only keep groups having <predicate> satisfied
  5. SELECT <column list> - select columns in <column list> to keep
    1. [DISTINCT] - keep only distinct rows (filter out duplicates)
  6. [ORDER BY <column list> [DESC/ASC]] - order the output by value of the columns in <column list>, ASCending by default
  7. [LIMIT <amount>] - limit the output to just the first <amount> rows

  • DBMS may execute a query in an equivalent but different order
  • For multi-table queries: perform joins with FROM

9 of 63

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.

10 of 63

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.

11 of 63

Logical Processing Order

FROM test_table�WHERE a > 2GROUP 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

12 of 63

Logical Processing Order

FROM test_table�WHERE a > 2GROUP 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

13 of 63

Logical Processing Order

c

0

1

SELECT b AS c�FROM test_table�WHERE a > 2GROUP 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

14 of 63

Logical Processing Order

c

0

1

SELECT DISTINCT b AS c�FROM test_table�WHERE a > 2GROUP 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

15 of 63

Logical Processing Order

c

1

0

SELECT DISTINCT b AS c�FROM test_table�WHERE a > 2GROUP BY b

HAVING COUNT(*) >= 2ORDER 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.

16 of 63

Logical Processing Order

c

1

SELECT DISTINCT b AS c�FROM test_table�WHERE a > 2GROUP BY b

HAVING COUNT(*) >= 2ORDER BY c DESC

LIMIT 1

c

1

0

Return just the first row.

17 of 63

A Note On GROUP BY

  • Consider the following Classes table and
    • Applying the query: SELECT <TBD> FROM Classes GROUP BY Dept;
    • This is what the table looks like once we perform the 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

18 of 63

A Note On GROUP BY

  • The role of the SELECT statement is to squash each group into a single row
    • In general, SELECT clauses are applied to each row, but when grouping is involved they are applied to each group

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

19 of 63

The Group By Rules

  • Columns can only be selected if they are a part of the group by clause or the selected column is an aggregate (i.e. MAX, MIN, AVG, etc.)

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

20 of 63

String Comparison

LIKE: following expression follows SQL specified format

  • _: Any single character
  • %: Zero, one, or more characters
  • Looks for a perfect string match

Examples:

  • LIKE ‘z%’ starts with z
  • LIKE ‘z_’ exactly 2 letters, 1st is z
  • LIKE ‘_z%’ 2nd letter is a z

~ : following expression follows regex format

  • . : Any single character
  • * : Zero, one, or more of the character preceding the symbol
  • ^: Match at start of string (If used outside [])
  • Looks for any pattern in the string that fits

Examples:

  • ~ ‘z.*’ contains z
  • ~ ‘^z.*’ starts with z

Note: ~ cannot be used in SQLite (which Project 1 will be using)

21 of 63

Practice: Single-Table Queries

22 of 63

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)

23 of 63

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

24 of 63

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)

25 of 63

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%'

26 of 63

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.*'

27 of 63

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)

28 of 63

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;

29 of 63

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)

30 of 63

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;

31 of 63

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)

32 of 63

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;

33 of 63

SQL Joins

34 of 63

Join Variants

  • The different types of joins determine what we do with rows that don’t ever match the “join condition”

SELECT * FROM

T1 INNER JOIN T2

ON T1.a = T2.a;

Join Condition

35 of 63

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;

36 of 63

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

37 of 63

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

38 of 63

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

39 of 63

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

40 of 63

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

41 of 63

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

42 of 63

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

43 of 63

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

44 of 63

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

45 of 63

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

46 of 63

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

47 of 63

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

48 of 63

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

49 of 63

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;

50 of 63

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

51 of 63

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;

52 of 63

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

53 of 63

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;

54 of 63

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

55 of 63

Practice: Multi-Table Joins

56 of 63

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)

57 of 63

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;

58 of 63

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)

59 of 63

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;

60 of 63

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)

61 of 63

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;

62 of 63

Appendix (Tips and Tricks)

  • Using an aggregate in WHERE is not allowed
    • WHERE COUNT(*) > 500 is an invalid query!
  • Don’t use HAVING without GROUP BY
    • Just use WHERE instead!
  • If GROUP BY is used, you can only SELECT columns that are aggregates OR are columns used to group by
  • DISTINCT removes all duplicate rows
    • Watch out for order of operators + logical processing order!
    • If you want to see how many distinct values there are of a column, DISTINCT COUNT(X) will not work; use COUNT(DISTINCT X)

63 of 63

Attendance Link