In this week's section, we'll practice writing SQL queries for several example databases. As we saw in lecture yesterday, we can use phpMyAdmin (which comes with MAMP) to create a database storing different tables (e.g. games database with a single table called Games).
For general query practice with a few practice tables, remember that you can you can also use the CSE 154 Query Tester, which is a tool to practice more queries.
Today, 4:30pm, MGH389
React is an industry favorite JavaScript library for building complex web applications with rapidly changing data.
By the end of this section, you should be able to:
.sql
file or .csv
file.
We've provided a few practice datasets for you to set up on your phpMyAdmin:
menu-data.csv
is a CSV file saved
from an Excel-like program, with a small collection of rows for items in a cafe menu.
setup-fooddata.sql
contains SQL
commands to create a table with nutritional data from the USDA food database.
setup-games.sql
also contains SQL
commands, creating the same table used in lecture yesterday.
Both .sql and .csv file types can be imported easily into your phpMyAdmin with a few button clicks!
You can follow this demo video (no audio) for creating your first database on phpMyAdmin using the menu-data.csv file.
You can find another demo video for creating a gamesdb database with a single Games table using the setup-games.sql file (you can follow the same process for setup-fooddata.sql).
For more details, make sure to follow the phpMyAdmin tutorial (you can find alternative directions for using MySQL on a command line here).
menu
tableIn this part, you'll have a chance to practice SQL queries with a small cafe menu! If you have successfully imported the menu-data.csv file and renamed the table "TABLE 1" to menu, this table will have the following structure:
id | name | category | subcategory | price | cost |
---|---|---|---|---|---|
1 | Blueberry Scone | Bakery | Scones | 3.50 | 0.75 |
2 | Blueberry Scone (Vegan) | Bakery | Scones | 3.50 | 0.85 |
3 | Chocolate Chip Scone | Bakery | Scones | 3.70 | 0.75 |
... | ... | ... | ... | ... | ... |
59 | Bubble Tea | Drinks | Tea | 4.00 | 5.50 |
For our first query, let's first see what's on the menu.
What query would lists all of the menu item names with their price in the menu table?
Solution:
SELECT name, price
FROM menu;
SQL
You should see 59 rows returned after executing this command in your MySQL console.
Write a query that lists the name, cost, and price of all menu items that contain the string "Coffee" in their name. Order the results by price (in ascending order).
+--------------------------------------+------+-------+
| name | cost | price |
+--------------------------------------+------+-------+
| Brewed Coffee (Black) | 0.65 | 1.25 |
| Brewed Coffee (With Cream) | 0.85 | 1.50 |
| Brewed Coffee (With Cream and Sugar) | 1.05 | 2.00 |
| Coffee Cake | 1.35 | 3.50 |
| Coffee Cake (Vegan) | 1.55 | 3.50 |
+--------------------------------------+------+-------+
5 rows in set (0.01 sec)
Expected results
One solution is provided below:
SELECT name, cost, price
FROM menu
WHERE name LIKE "%Coffee%";
SQL
Write a query that lists the name, price, and category of all menu items that are sold for a price less than $2.00. Order the results by price in descending order, breaking ties by name alphabetically.
+----------------------------+-------+----------+
| name | price | category |
+----------------------------+-------+----------+
| Brewed Coffee (With Cream) | 0.85 | Drinks |
| Plain Toast | 0.65 | Bakery |
| Brewed Coffee (Black) | 1.25 | Drinks |
| ... | ... | ... |
| Iced Water | 1.55 | Drinks |
+----------------------------+-------+----------+
8 rows in set (0.01 sec)
Expected results
One solution is provided below:
SELECT name, price, category
FROM menu
WHERE price < 2
ORDER BY price DESC, name;
SQL
It looks like there's an item that costs the cafe more than it sells for! Can you write a query to find the name of the item?
SELECT name
FROM menu
WHERE price < cost
SQL
Write a query that lists the name, price, and cost of the most expensive menu item on the menu (by price).
One possible solution is provided below:
SELECT name, price, cost
FROM menu
ORDER BY price DESC
LIMIT 1;
SQL
In this part of the section, we will use the video game dataset provided (seen in Wednesday's lecture). This dataset has a table called Games which we will write queries with. There are approximately 3000 rows of video game data in this table.
id | name | platform | release_year | genre | publisher | developer | rating |
---|---|---|---|---|---|---|---|
1 | Pokemon Red/Blue | GB | 1996 | Role-Playing | Nintendo | Game Freak | E |
2 | Spyro Reignited Trilogy | PS4 | 2018 | Platform | Activision | Toys for Bob | E |
3 | Universal Paperclips | PC | 2017 | World Domination | Frank Lantz | Frank Lantz | E |
... | ... | ... | ... | ... | ... | ... | ... |
Write a SQL query that returns the names of all games that were developed by Nintendo (your result should not have duplicates).
+---------------------------+
| name |
+---------------------------+
| Mario Kart Wii |
| New Super Mario Bros. |
| New Super Mario Bros. Wii |
| Mario Kart DS |
| Wii Fit |
| ... |
+---------------------------+
63 rows in set (0.01 sec)
Expected results (first 5 rows)
One solution is provided below:
SELECT DISTINCT name
FROM Games
WHERE developer = 'Nintendo';
SQL
Write a SQL query that returns a list of all distinct game platforms in the Games table (e.g., Wii).
+----------+
| platform |
+----------+
| GB |
| PS4 |
| PC |
| NES |
| PS |
| Wii |
| ... |
+----------+
26 rows in set (0.01 sec)
Expected results (first 6 rows)
One solution is provided below:
SELECT DISTINCT platform
FROM Games;
SQL
Write a SQL query that returns the names and release year of 20 of the video games released earliest as determined by their release_year in the Games table.
+-----------------------------+--------------+
| name | release_year |
+-----------------------------+--------------+
| Combat | 1977 |
| Space Invaders | 1978 |
| Defender | 1980 |
| Asteroids | 1980 |
| Missile Command | 1980 |
| ... | ... |
+-----------------------------+--------------+
20 rows in set (0.01 sec)
Expected results (first 5 rows)
One solution is provided below:
SELECT name, release_year
FROM Games
ORDER BY release_year
LIMIT 20;
SQL
Write a SQL query that returns the name, platform and release year of all games with the word 'Spyro' in their title and which don't include 'Skylanders' in their title. Hint: Use NOT to negate a boolean expression in MySQL.
+----------------------------+----------+--------------+
| name | platform | release_year |
+----------------------------+----------+--------------+
| Spyro Reignited Trilogy | PS4 | 2018 |
| Spyro the Dragon | PS | 1998 |
| Spyro: Year of the Dragon | PS | 2000 |
| Spyro 2: Ripto's Rage | PS | 1999 |
| Spyro: Season of Ice | GBA | 2001 |
| ... | ... | ... |
+----------------------------+----------+--------------+
8 rows in set (0.01 sec)
Expected results (first 5 rows)
One solution is provided below:
SELECT name, platform, release_year
FROM Games
WHERE name LIKE '%Spyro%'
AND NOT (name LIKE '%Skylanders%');
SQL
Note: This is a challenge query! We'll review ways to approach the solution in upcoming lectures, but feel free to see how far you can get using what we've covered (and the cheatsheet)!
Write a SQL query that returns the name and release_year of the Puzzle games released in the earliest year for Puzzle games in the Games table. How does the result for Puzzle games compare to Sports games?
+-----------------------------+--------------+
| name | release_year |
+-----------------------------+--------------+
| Ms. Pac-Man | 1981 |
+-----------------------------+--------------+
1 rows in set (0.02 sec)
Expected results
One solution is provided below (you can nest SELECT to return specific values like MIN):
SELECT g1.name, g1.release_year
FROM Games g1
WHERE g1.genre = 'puzzle'
AND g1.release_year = (SELECT MIN(g2.release_year)
FROM Games g2
WHERE g2.genre = 'puzzle');
SQL
Write a SQL query that returns the average release_year of games in the Games table. Use the ROUND function to round the result to the nearest integer and rename the column with an alias avg_release_year.
+------------------+
| avg_release_year |
+------------------+
| 2005 |
+------------------+
1 row in set (0.01 sec)
Expected result
One solution is provided below:
SELECT ROUND(AVG(release_year)) as avg_release_year
FROM Games;
SQL
Next, you'll use the smaller food_data table to fetch some data about food nutrition info found from the USDA nutrition database. Each food listed has data for a 100g serving, which makes it useful to compare nutrition information between different foods.
The following table (called a schema) shows the different types of data (as columns) in the food_data table for each food item (row), where protein and carbs are given in grams:
id | description | protein | carb |
---|---|---|---|
9427 | Abiyuch, raw | 1.5 | 17.6 |
9002 | Acerola juice, raw | 0.40 | 4.80 |
... | ... | ... | ... |
What query would lists all of the food descriptions in the food_data table?
Solution:
SELECT description
FROM food_data;
SQL
You should see a 2371 rows returned after executing this command in your MySQL console.
Write a query that returns all of the food descriptions, grams of protein, and grams of carb for food_data items that have more grams protein than carbs per 100g (remember that all data is given for 100g in this dataset). Your result should be in whatever order as defined by the table (no explicit ordering).
+-----------------------+---------+------+
| description | protein | carb |
+-----------------------+---------+------+
| Butter, salted | 0.85 | 0.06 |
| Butter oil, anhydrous | 0.28 | 0.00 |
| Cheese, blue | 21.40 | 2.34 |
| Cheese, brick | 23.24 | 2.79 |
| Cheese, brie | 20.75 | 0.45 |
| ... | ... | ... |
+-----------------------+---------+------+
191 rows in set (0.01 sec)
Expected results (first 8 rows)
One solution is provided below:
SELECT description, protein, carb
FROM food_data
WHERE protein > carb;
SQL
Write a query to return the descriptions, grams of protein, and grams of carbohydrates for foods that have more grams of protein than carbohydrates and which have the word 'cooked' in their description. Order the results by alphabetical order.
+----------------------------------------------------------+---------+-------+
| description | protein | carb |
+----------------------------------------------------------+---------+-------+
| Asparagus, frozen, cooked, boiled, drained, with salt | 2.95 | 1.92 |
| Asparagus, frozen, cooked, boiled, drained, without salt | 2.95 | 1.92 |
| Bamboo shoots, cooked, boiled, drained, with salt | 1.53 | 1.52 |
| Broccoli raab, cooked | 3.83 | 3.12 |
| Cowpeas, leafy tips, cooked, boiled, drained, with salt | 4.67 | 2.80 |
| ... | ... | ... |
+----------------------------------------------------------+---------+-------+
18 rows in set (0.01 sec)
Expected results (first 5 rows)
One solution is provided below:
SELECT description, protein, carb
FROM food_data
WHERE protein > carb AND description LIKE '%cooked%'
ORDER BY description;
SQL
Next, modify your answer from Query 3 to also include a new column containing the grams of protein rounded to the nearest whole integer. Omit the protein and carb columns in this query. You can use an alias to add a new named column to the result table.
For example, to create an alias for a new column named my_alias for adding protein and carb grams per record, we could do:
SELECT (protein + carb) as my_alias FROM food_data;
You can use the
ROUND(x, y)
function in MySQL which truncates x to have exacty y decimal places.
In this case, round to 0 decimal places. Refer to the slide below for the expected output results.
+----------------------------------------------------------+-----------------+
| description | percent_protein |
+----------------------------------------------------------+-----------------+
| Asparagus, frozen, cooked, boiled, drained, with salt | 3 |
| Asparagus, frozen, cooked, boiled, drained, without salt | 3 |
| Bamboo shoots, cooked, boiled, drained, with salt | 2 |
| Broccoli raab, cooked | 4 |
| Cowpeas, leafy tips, cooked, boiled, drained, with salt | 5 |
| ... | ... |
+----------------------------------------------------------+-----------------+
12 rows in set (0.01 sec)
Expected results (first 5 rows)
One solution is provided below:
SELECT description, ROUND(protein) as percent_protein
FROM food_data
WHERE protein > carb AND description LIKE '%cooked%'
ORDER BY description;
SQL
Write a query to return the descriptions of foods that have the word 'apple' in them. Order the results in descending order by description.
+-------------------------------------------------------------------------+
| description |
+-------------------------------------------------------------------------+
| Sugar-apples, (sweetsop), raw |
| Ruby Red grapefruit juice blend (grapefruit, grape, apple), OCEAN SPRAY |
| Pineapple, raw, traditional varieties |
| Pineapple, raw, extra sweet variety |
| Pineapple, raw, all varieties |
| ... |
+-------------------------------------------------------------------------+
75 rows in set (0.00 sec)
Expected results (first 5 rows)
One solution is provided below:
SELECT description
FROM food_data
WHERE description LIKE '%apple%'
ORDER BY description DESC;
SQL
You can use the CSE 154 Query Tester tool to practice writing queries for a few databases. The query tester is located here.
world
Database (by Sylvia Tashev, Stefanie Hatcher)This database includes tables containing information about countries, cities, and languages (note that this database isn't up to date, but still is useful for practicing queries). The schema for the three tables are on the next three slides below.
code | name | continent | population | gnp | ... |
---|---|---|---|---|---|
AFG | Afghanistan | Asia | 22720000 | 5976.0 | ... |
NLD | Netherlands | Europe | 15864000 | 371362.0 | ... |
... | ... | ... | ... | ... | ... |
id | name | country_code | district | population |
---|---|---|---|---|
3793 | New York | USA | New York | 8008278 |
1 | Los Angeles | USA | California | 3694820 |
... | ... | ... | ... | ... |
country_code | language | official | percentage |
---|---|---|---|
AFG | Pashto | T | 52.4 |
NLD | Dutch | T | 95.6 |
... | ... | ... | ... |
List all of the official languages spoken around the world in reverse alphabetical order.
+------------+
| language |
+------------+
| Zulu |
| Xhosa |
| Wolof |
| Vietnamese |
| Uzbek |
| ... |
+------------+
102 rows in set (0.02 sec)
Expected results (first 5 rows)
One solution is provided below:
SELECT DISTINCT language
FROM languages
WHERE official='T'
ORDER BY language DESC;
SQL
What countries have the word Republic
as part of their name?
+---------------------------------------+
| name |
+---------------------------------------+
| Dominican Republic |
| Central African Republic |
| Congo, The Democratic Republic of the |
| Czech Republic |
+---------------------------------------+
4 rows in set (0.00 sec)
Expected results
One solution is provided below:
SELECT name
FROM countries
WHERE name LIKE '%Republic%';
SQL
List the names of all countries that are not in Africa.
+--------------------------+
| name |
+--------------------------+
| Afghanistan |
| Netherlands |
| Netherlands Antilles |
| Albania |
| American Samoa |
| ... |
+--------------------------+
181 rows in set (0.00 sec)
Expected results (first 5 rows)
Two solutions are provided below. Note that the first uses !=
and the second
uses <>
for the inequality operators.
SELECT name
FROM countries
WHERE continent != 'Africa';
SQL
SELECT name
FROM countries
WHERE continent <> 'Africa';
SQL
Which countries have a GNP between $10,000 AND $50,000? Write a query that returns the name and gnp of these countries.
+------------------------+----------+
| name | gnp |
+------------------------+----------+
| Algeria | 49982.00 |
| United Arab Emirates | 37966.00 |
| Bangladesh | 32852.00 |
| Brunei | 11705.00 |
| Bulgaria | 12178.00 |
...
+------------------------+----------+
36 rows in set (0.00 sec)
Expected results (first 5 rows)
SELECT name, gnp
FROM countries
WHERE gnp BETWEEN 10000 AND 50000;
SQL
You can also use:
SELECT name, gnp
FROM countries
WHERE gnp < 50000
AND gnp > 10000;
SQL
Which countries have the densest population (population divided by surface area)? Write a query that returns the name, population, surface_area, and population_density of all countries, ordered by population densities (descending).
+------------+------------+--------------+--------------------+
| name | population | surface_area | population_density |
+------------+------------+--------------+--------------------+
| Macao | 473000 | 18.00 | 26277.777778 |
| Monaco | 34000 | 1.50 | 22666.666667 |
| Hong Kong | 6782000 | 1075.00 | 6308.837209 |
| Singapore | 3567000 | 618.00 | 5771.844660 |
| Gibraltar | 25000 | 6.00 | 4166.666667 |
| ... | ... | ... | ... |
+------------+------------+--------------+--------------------+
239 rows in set (0.00 sec)
Expected results (first 5 rows)
SELECT name, population, surface_area,
population / surface_area as population_density
FROM countries
ORDER BY population_density DESC;
SQL
List the country_codes for all countries where English is spoken as an official language.
+--------------+
| country_code |
+--------------+
| AIA |
| ASM |
| ATG |
| BLZ |
| BMU |
| ... |
+--------------+
44 rows in set (0.02 sec)
Expected results (first 5 rows)
SELECT country_code
FROM languages
WHERE language = 'English' AND official = 'T';
SQL