In this post, we’ll be going over how to solve the SQL Library Lab found on Learn.co. This lab covers writing SQL statements with complex relationships. We’re going to be following the structure in the lab, so fork and clone the files. Also keep running the rspec tests included to gauge your progress.
SECTION 1: SCHEMA.SQL
Build out the schema for our Fantasy Library database. Setting up the tables is pretty straightforward. We’re just creating basic tables with columns and data types outlined by the lab and tests.
The columns that have _id
allow us to create associations with other tables. The series_id
in the characters
table, allows us to set the fantasy series that a character belongs to.
Books have many characters and characters can appear in many books. We’ll need a join table in order to create that complex relationship. That means we need a table that stores the key of a character with the key of the books that character belongs to.
SECTION 2: INSERT.SQL
Populate the database with data. You can make up your own, but the SQL statements are going to look something like the code below. The main thing to remember is the syntax for inserting into the table and the order of the columns and values.
The statement is telling our database to work on the books
table and match the columns (id, title, year, series_id)
with the values to be inserted in the same order (1, "Game of Thrones", 1996, 1)
, and multiple sets of values are comma separated.
SECTION 3: UPDATE.SQL
Update the species of the last character in the database to “Martian” by writing an update statement in update.sql
file. Update statements are pretty straightforward as well, just remember the syntax!
What the above statement is selecting the row in the characters
table, where the characters.id
is equal to 8 (our last character), and then sets the species
column value to 'Martian'
SECTION 4: QUERYING YOUR DATABASE
Check spec/querying_spec.rb
, complete the tests by writing the appropriate queries to satisfy the queries in the querying.rb
file. Note that for this section, the database will be seeded with external data so don’t expect it to reflect the data you added above. The methods to be called are already named in the ruby file, we just need to write the sql statements that would return the desired values.
Let’s break down one of the more complex statements. The method select_series_title_with_most_human_characters
should be interesting to write. What we’ll need is the series title name that has the most human characters across it’s books.
Let’s break down what’s happening here. We don’t have a direct relationship for us to get the information we need, so we’re going to create some joins to bridge the gaps. We’re going to have bridge our series
-> books
-> character_books
-> characters
where the species
are of the character is human.
SELECT series.title FROM series
is saying we want the title
of the series from the series
table.
JOIN books ON series.id = books.series_id
here we’re joining the books
table with the series
table where id of the series matches the series_id
of entries in the books
table.
JOIN character_books ON books.id = character_books.book_id
is using the join table character_books
to get the characters associated with books from our first join.
JOIN characters ON character_books.character_id = characters.id
gets the characters in the books, where books are part of a series retrieved from former joins.
WHERE characters.species = 'human'
is limiting our characters to only those who are human.
GROUP BY series.title ORDER BY COUNT(*) DESC
is sorting all of the series returned by the number of human characters, with the highest number of characters at the top and descending to the lowest at the bottom. We use GROUP BY
keyword because we are using an aggregate function COUNT
.
LIMIT 1
is saying we want to only have the first result, which is the series.title
that has the most human characters due to our ORDER BY
and DESC
sorts.
Fill out the rest of the methods and make sure to pass all the tests! Happy coding!