Lab 10 Solutions

Solution Files

Required Questions

SQL

A SELECT statement describes an output table based on input rows. To write one:

  1. Describe the input rows using FROM and WHERE clauses.
  2. Format and order the output rows and columns using SELECT and ORDER BY clauses.

SELECT (Step 3) FROM (Step 1) WHERE (Step 1) ORDER BY (Step 3);

The WHERE and ORDER BY clauses are optional.

Consult the drop-down for a refresher on SQL. It's okay to skip directly to the questions and refer back here should you get stuck.

SQL Basics

Creating Tables

You can create SQL tables either from scratch or from existing tables.

The following statement creates a table by specifying column names and values without referencing another table. Each SELECT clause specifies the values for one row, and UNION is used to join rows together. The AS clauses give a name to each column; it need not be repeated in subsequent rows after the first.

CREATE TABLE [table_name] AS
  SELECT [val1] AS [column1], [val2] AS [column2], ... UNION
  SELECT [val3]             , [val4]             , ... UNION
  SELECT [val5]             , [val6]             , ...;

Let's say we want to make the following table called big_game which records the scores for the Big Game each year. This table has three columns: berkeley, stanford, and year.

We could do so with the following CREATE TABLE statement:

CREATE TABLE big_game AS
  SELECT 30 AS berkeley, 7 AS stanford, 2002 AS year UNION
  SELECT 28,             16,            2003         UNION
  SELECT 17,             38,            2014;

Selecting From Tables

More commonly, we will create new tables by selecting specific columns that we want from existing tables by using a SELECT statement as follows:

SELECT [columns] FROM [tables] WHERE [condition] ORDER BY [columns] LIMIT [limit];

Let's break down this statement:

  • SELECT [columns] tells SQL that we want to include the given columns in our output table; [columns] is a comma-separated list of column names, and * can be used to select all columns
  • FROM [table] tells SQL that the columns we want to select are from the given table
  • WHERE [condition] filters the output table by only including rows whose values satisfy the given [condition], a boolean expression
  • ORDER BY [columns] orders the rows in the output table by the given comma-separated list of columns
  • LIMIT [limit] limits the number of rows in the output table by the integer [limit]

Here are some examples:

Select all of Berkeley's scores from the big_game table, but only include scores from years past 2002:

sqlite> SELECT berkeley FROM big_game WHERE year > 2002;
28
17

Select the scores for both schools in years that Berkeley won:

sqlite> SELECT berkeley, stanford FROM big_game WHERE berkeley > stanford;
30|7
28|16

Select the years that Stanford scored more than 15 points:

sqlite> SELECT year FROM big_game WHERE stanford > 15;
2003
2014

SQL operators

Expressions in the SELECT, WHERE, and ORDER BY clauses can contain one or more of the following operators:

  • comparison operators: =, >, <, <=, >=, <> or != ("not equal")
  • boolean operators: AND, OR
  • arithmetic operators: +, -, *, /
  • concatenation operator: ||

Output the ratio of Berkeley's score to Stanford's score each year:

sqlite> select berkeley * 1.0 / stanford from big_game;
0.447368421052632
1.75
4.28571428571429

Output the sum of scores in years where both teams scored over 10 points:

sqlite> select berkeley + stanford from big_game where berkeley > 10 and stanford > 10;
55
44

Output a table with a single column and single row containing the value "hello world":

sqlite> SELECT "hello" || " " || "world";
hello world

Usage

First, check that a file named sqlite_shell.py exists alongside the assignment files. If you don't see it, or if you encounter problems with it, scroll down to the Troubleshooting section to see how to download an official precompiled SQLite binary before proceeding.

You can start an interactive SQLite session in your Terminal or Git Bash with the following command:

python3 sqlite_shell.py

While the interpreter is running, you can type .help to see some of the commands you can run.

To exit out of the SQLite interpreter, type .exit or .quit or press Ctrl-C. Remember that if you see ...> after pressing enter, you probably forgot a ;.

You can also run all the statements in a .sql file by doing the following: (Here we're using the lab13.sql file as an example.)

  1. Runs your code and then exits SQLite immediately afterwards.

    python3 sqlite_shell.py < lab13.sql
  2. Runs your code and then opens an interactive SQLite session, which is similar to running Python code with the interactive -i flag.

    python3 sqlite_shell.py --init lab13.sql

Happy Turkey Day

No turkeys were harmed in the creation of this lab.

The turkeys table has columns age (numbers) in months, weight (numbers) in kilograms, and name (string) and a row for each turkey on a farm.

CREATE TABLE turkeys AS
  SELECT 18 AS age, 16.5 AS weight, "Pecan" AS name UNION
  SELECT 30       , 22.1          , "Waddle"        UNION
  SELECT 12       , 17.3          , "Bud"           UNION
  SELECT 14       , 15.3          , "Bird"          UNION
  SELECT 30       , 26.8          , "Tom"           UNION
  SELECT 26       , 18.4          , "Flappy"        UNION
  SELECT 18       , 19.3          , "Pumpkin";

Q1: Big Ones

Create a big table with two columns, name (strings) and pounds (numbers), that has a row for each turkey in the turkeys table that weighs more than 18 kilograms. The name column should contain the name of the turkey, and rows should appear in alphabetical order by name. The pounds column should contain the weight of the turkey in pounds. Assume a kilogram is exactly 2.2 pounds.

Your query should work correctly for any data that might appear in the turkeys table, but for the example above the result should be:

name     pounds
-------  ------
Flappy   40.48
Pumpkin  42.46
Tom      58.96
Waddle   48.62
  SELECT name, _______ AS pounds
    FROM turkeys
    WHERE _______
    ORDER BY _______;
  1. Use WHERE to create a row for each turkey above 18 kilograms in weight.
  2. Use ORDER BY to order the rows alphabetically by name.
  3. Use SELECT to compute each turkey's weight in pounds.
CREATE TABLE big AS
SELECT name, weight * 2.2 AS pounds FROM turkeys WHERE weight > 18 ORDER BY name;
Use Ok to test your code:

python3 ok -q big

Q2: Growing Up

A turkey is expected to increase in weight by 1 kilogram each month until it is 24 months old. After 24 months, it is not expected to grow.

Create a growing table with two columns, name (strings) and full (numbers), that contains a row for every turkey that is expected to be more than 25 kilograms when full grown at 24 months. The name column contains the name of the turkey. The full column contains the expected full size of the turkey at 24 months (or more). The names should appear in the same order as they do in the turkeys table.

Your query should work correctly for any data that might appear in the turkeys table, but for the example above the result should be:

name     full
-------  ----
Bud      29.3
Bird     25.3
Pumpkin  25.3
Tom      26.8

Hint: Use MAX and MIN to compute the max or min of two numbers, such as MAX(2, 3).

SELECT name, _______ AS full
  FROM turkeys
  WHERE full > 25;
CREATE TABLE growing AS
SELECT name, weight + max(0, 24-age) AS full FROM turkeys WHERE full > 25;
Use Ok to test your code:

python3 ok -q growing

Check Your Score Locally

You can locally check your score on each question of this assignment by running

python3 ok --score

This does NOT submit the assignment! When you are satisfied with your score, submit the assignment to Gradescope to receive credit for it.

Submit Assignment

Submit this assignment by uploading any files you've edited to the appropriate Gradescope assignment. Lab 00 has detailed instructions.