diff --git a/concepts/select/.meta/config.json b/concepts/select/.meta/config.json new file mode 100644 index 00000000..5442fc00 --- /dev/null +++ b/concepts/select/.meta/config.json @@ -0,0 +1,5 @@ +{ + "blurb": "The SQL SELECT statement is the mechanism for querying a database.", + "authors": ["blackk-foxx"], + "contributors": ["blackk-foxx"] +} diff --git a/concepts/select/about.md b/concepts/select/about.md new file mode 100644 index 00000000..f0d88dbc --- /dev/null +++ b/concepts/select/about.md @@ -0,0 +1,132 @@ +# The SELECT statement + +In SQL, a `SELECT` statement allows you to retrieve data from a database. +The result of a `SELECT` statement is a result set. +A result set contains values arranged in rows and columns. +Each column is a particular attribute of the data. +Each row contains a value for every column. + +One way to think about it is that a set of columns represents a data structure, where each column represents a field of the data structure, and each row represents an instance of the data structure. + +With a `SELECT` statement, you can specify the data you want to retrieve. +You can also optionally transform, filter, and/or modify the shape of the output data. + +## The basics + +The anatomy of a basic `SELECT` statement is as follows: + +```sql +SELECT +FROM +WHERE ; +``` + +~~~~exercism/note +The `FROM` and `WHERE` clauses are optional. +For example, a statement like `SELECT "Hello, world.";` is perfectly valid. + +Also note that the line breaks are not required; any spacing will suffice to separate the different clauses (i.e. parts) of the `SELECT` statement. +~~~~ + +Immediately following the `SELECT` keyword is a list of the columns that you want in the result. +The `FROM` clause identifies the source of the data, which is typically a table in the database. +The `WHERE` clause filters the output data by one or more criteria. + +For example, consider a database with a table named `inventory` containing the following data: + +| upc | category | supplier | brand | product_name | weight | stock | +|--------------|------------|----------------|-------------|----------------------------------|--------|-------| +| 812345670019 | Cookware | KitchenCo | HearthStone | 10" Non-Stick Skillet | 1.8 | 42 | +| 845678120334 | Utensils | HomePro Supply | PrepMaster | Stainless Steel Ladle | 0.4 | 120 | +| 899001234556 | Appliances | Culinary Depot | QuickBrew | Single-Serve Coffee Maker | 4.2 | 18 | +| 823450987112 | Cookware | KitchenCo | FreshKeep | 12-Piece Glass Container Set | 6 | 33 | +| 867530900221 | Utensils | HomePro Supply | EdgeCraft | 8' Chef's Knife | 0.6 | 27 | +| 880012349876 | Appliances | Culinary Depot | HeatWave | Compact Toaster Oven | 7.5 | 14 | +| 833221109443 | Utensils | HomePro Supply | PureScrub | Heavy-Duty Kitchen Sponge (3-pk) | 0.2 | 200 | +| 899998877665 | Cookware | KitchenCo | IronCraft | Cast-Iron Grill Pan | 5.3 | 21 | +| 844110220987 | Appliances | Culinary Depot | BlendPro | High-Speed Personal Blender | 3.1 | 16 | + +If we want to retrieve all of the data from the table, we could run the following query: + +```sql +SELECT * FROM inventory; +``` + +Result: + +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- ----------- -------------------------------- ------ ----- +812345670019 Cookware KitchenCo HearthStone 10" Non-Stick Skillet 1.8 42 +845678120334 Utensils HomePro Supply PrepMaster Stainless Steel Ladle 0.4 120 +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +823450987112 Cookware KitchenCo FreshKeep 12-Piece Glass Container Set 6 33 +867530900221 Utensils HomePro Supply EdgeCraft 8' Chef's Knife 0.6 27 +880012349876 Appliances Culinary Depot HeatWave Compact Toaster Oven 7.5 14 +833221109443 Utensils HomePro Supply PureScrub Heavy-Duty Kitchen Sponge (3-pk) 0.2 200 +899998877665 Cookware KitchenCo IronCraft Cast-Iron Grill Pan 5.3 21 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` + +If we only want the category and product_name values, we could specify those columns: + +```sql +SELECT category, product_name FROM inventory; +``` + +Result: + +``` +category product_name +---------- -------------------------------- +Cookware 10" Non-Stick Skillet +Utensils Stainless Steel Ladle +Appliances Single-Serve Coffee Maker +Cookware 12-Piece Glass Container Set +Utensils 8' Chef's Knife +Appliances Compact Toaster Oven +Utensils Heavy-Duty Kitchen Sponge (3-pk) +Cookware Cast-Iron Grill Pan +Appliances High-Speed Personal Blender +``` + +## Filtering data with the WHERE clause + +The `WHERE` clause allows you to filter the data retrieved by a `SELECT` statement. +For example, if we only want Appliances, we can do the following: + +```sql +SELECT * FROM inventory +WHERE category = "Appliances"; +``` + +Result: +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- --------- --------------------------- ------ ----- +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +880012349876 Appliances Culinary Depot HeatWave Compact Toaster Oven 7.5 14 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` + +Or maybe we only want data where the weight is between 2.0 and 6.0: + +```sql +SELECT * FROM inventory +WHERE weight BETWEEN 2.0 AND 6.0; +``` + +Result: +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- --------- ---------------------------- ------ ----- +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +823450987112 Cookware KitchenCo FreshKeep 12-Piece Glass Container Set 6 33 +899998877665 Cookware KitchenCo IronCraft Cast-Iron Grill Pan 5.3 21 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` + +In addition to `=` and `BETWEEN...AND`, the `WHERE` clause supports a wide range of expressions, including comparison (`<`, `<=`, `>`, `>=`), pattern matching (`LIKE`, `GLOB`, `REGEXP`, `MATCH`), and checking for membership in a list (`IN`, `NOT IN`). +See [SQL Language Expressions](sql-expr) for the complete documentation. + +[sql-expr]: https://sqlite.org/lang_expr.html diff --git a/concepts/select/introduction.md b/concepts/select/introduction.md new file mode 100644 index 00000000..1f799474 --- /dev/null +++ b/concepts/select/introduction.md @@ -0,0 +1,132 @@ +# Introduction + +In SQL, a `SELECT` statement allows you to retrieve data from a database. +The result of a `SELECT` statement is a result set. +A result set contains values arranged in rows and columns. +Each column is a particular attribute of the data. +Each row contains a value for every column. + +One way to think about it is that a set of columns represents a data structure, where each column represents a field of the data structure, and each row represents an instance of the data structure. + +With a `SELECT` statement, you can specify the data you want to retrieve. +You can also optionally transform, filter, and/or modify the shape of the output data. + +## The basics + +The anatomy of a basic `SELECT` statement is as follows: + +```sql +SELECT +FROM +WHERE ; +``` + +~~~~exercism/note +The `FROM` and `WHERE` clauses are optional. +For example, a statement like `SELECT "Hello, world.";` is perfectly valid. + +Also note that the line breaks are not required; any spacing will suffice to separate the different clauses (i.e. parts) of the `SELECT` statement. +~~~~ + +Immediately following the `SELECT` keyword is a list of the columns that you want in the result. +The `FROM` clause identifies the source of the data, which is typically a table in the database. +The `WHERE` clause filters the output data by one or more criteria. + +For example, consider a database with a table named `inventory` containing the following data: + +| upc | category | supplier | brand | product_name | weight | stock | +|--------------|------------|----------------|-------------|----------------------------------|--------|-------| +| 812345670019 | Cookware | KitchenCo | HearthStone | 10" Non-Stick Skillet | 1.8 | 42 | +| 845678120334 | Utensils | HomePro Supply | PrepMaster | Stainless Steel Ladle | 0.4 | 120 | +| 899001234556 | Appliances | Culinary Depot | QuickBrew | Single-Serve Coffee Maker | 4.2 | 18 | +| 823450987112 | Cookware | KitchenCo | FreshKeep | 12-Piece Glass Container Set | 6 | 33 | +| 867530900221 | Utensils | HomePro Supply | EdgeCraft | 8' Chef's Knife | 0.6 | 27 | +| 880012349876 | Appliances | Culinary Depot | HeatWave | Compact Toaster Oven | 7.5 | 14 | +| 833221109443 | Utensils | HomePro Supply | PureScrub | Heavy-Duty Kitchen Sponge (3-pk) | 0.2 | 200 | +| 899998877665 | Cookware | KitchenCo | IronCraft | Cast-Iron Grill Pan | 5.3 | 21 | +| 844110220987 | Appliances | Culinary Depot | BlendPro | High-Speed Personal Blender | 3.1 | 16 | + +If we want to retrieve all of the data from the table, we could run the following query: + +```sql +SELECT * FROM inventory; +``` + +Result: + +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- ----------- -------------------------------- ------ ----- +812345670019 Cookware KitchenCo HearthStone 10" Non-Stick Skillet 1.8 42 +845678120334 Utensils HomePro Supply PrepMaster Stainless Steel Ladle 0.4 120 +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +823450987112 Cookware KitchenCo FreshKeep 12-Piece Glass Container Set 6 33 +867530900221 Utensils HomePro Supply EdgeCraft 8' Chef's Knife 0.6 27 +880012349876 Appliances Culinary Depot HeatWave Compact Toaster Oven 7.5 14 +833221109443 Utensils HomePro Supply PureScrub Heavy-Duty Kitchen Sponge (3-pk) 0.2 200 +899998877665 Cookware KitchenCo IronCraft Cast-Iron Grill Pan 5.3 21 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` + +If we only want the category and product_name values, we could specify those columns: + +```sql +SELECT category, product_name FROM inventory; +``` + +Result: + +``` +category product_name +---------- -------------------------------- +Cookware 10" Non-Stick Skillet +Utensils Stainless Steel Ladle +Appliances Single-Serve Coffee Maker +Cookware 12-Piece Glass Container Set +Utensils 8' Chef's Knife +Appliances Compact Toaster Oven +Utensils Heavy-Duty Kitchen Sponge (3-pk) +Cookware Cast-Iron Grill Pan +Appliances High-Speed Personal Blender +``` + +## Filtering data with the WHERE clause + +The `WHERE` clause allows you to filter the data retrieved by a `SELECT` statement. +For example, if we only want Appliances, we can do the following: + +```sql +SELECT * FROM inventory +WHERE category = "Appliances"; +``` + +Result: +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- --------- --------------------------- ------ ----- +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +880012349876 Appliances Culinary Depot HeatWave Compact Toaster Oven 7.5 14 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` + +Or maybe we only want data where the weight is between 2.0 and 6.0: + +```sql +SELECT * FROM inventory +WHERE weight BETWEEN 2.0 AND 6.0; +``` + +Result: +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- --------- ---------------------------- ------ ----- +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +823450987112 Cookware KitchenCo FreshKeep 12-Piece Glass Container Set 6 33 +899998877665 Cookware KitchenCo IronCraft Cast-Iron Grill Pan 5.3 21 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` + +In addition to `=` and `BETWEEN...AND`, the `WHERE` clause supports a wide range of expressions, including comparison (`<`, `<=`, `>`, `>=`), pattern matching (`LIKE`, `GLOB`, `REGEXP`, `MATCH`), and checking for membership in a list (`IN`, `NOT IN`). +See [SQL Language Expressions](sql-expr) for the complete documentation. + +[sql-expr]: https://sqlite.org/lang_expr.html diff --git a/concepts/select/links.json b/concepts/select/links.json new file mode 100644 index 00000000..58fcb18f --- /dev/null +++ b/concepts/select/links.json @@ -0,0 +1,10 @@ +[ + { + "url": "https://sqlite.org/lang_select.html#simple_select_processing", + "description": "Simple SELECT processing details" + }, + { + "url": "https://sqlite.org/lang_select.html", + "description": "Complete SELECT documentation for SQLite" + } +] diff --git a/config.json b/config.json index 4ecaaded..db8c5767 100644 --- a/config.json +++ b/config.json @@ -33,6 +33,17 @@ ] }, "exercises": { + "concept": [ + { + "slug": "weather-report", + "name": "Weather Report", + "uuid": "1762549a-4622-442d-9aff-4c65f72a955c", + "concepts": [ + "select" + ], + "prerequisites": [] + } + ], "practice": [ { "slug": "hello-world", @@ -716,6 +727,13 @@ "icon": "small" } ], + "concepts": [ + { + "uuid": "92187df0-fb68-4b46-af3b-cc17c2ef6fbc", + "slug": "select", + "name": "SELECT" + } + ], "tags": [ "execution_mode/interpreted", "platform/linux", diff --git a/exercises/concept/weather-report/.docs/hints.md b/exercises/concept/weather-report/.docs/hints.md new file mode 100644 index 00000000..e69de29b diff --git a/exercises/concept/weather-report/.docs/instructions.md b/exercises/concept/weather-report/.docs/instructions.md new file mode 100644 index 00000000..9a7f1bc4 --- /dev/null +++ b/exercises/concept/weather-report/.docs/instructions.md @@ -0,0 +1,30 @@ +# Instructions + +You are a data analyst at a firm that analyzes weather data in the Pacific Northwest. +You will be working with a database containing a `weather_readings` table with the following columns. + +* `date`: The date on which the sample was collected. +* `location`: The name of the city in which the sample was collected. +* `temperature`: The temperature, in degrees Fahrenheit. +* `wind_speed`: The wind speed, in miles per hour. + +In each of the following tasks, your job is to retrieve the specified result set, by using a `SELECT` statement. +Note that in each case, the result set will be stored in a new table -- one table for each task -- via a pre-written `CREATE TABLE` statement. +For now, don't worry about the `CREATE TABLE`; that will be covered in another lesson. +Just focus on adding the appropriate `SELECT` statement to accomplish the given task. + +## 1. Retrieve all of the data + +Retrieve all of the data from the `weather_readings` table. + +## 2. Retrieve only the location and temperature data + +Retrieve only the location and temperature values from the `weather_readings` table. + +## 3. Retrieve only data for Seattle + +Retrieve only the data for the Seattle location. + +## 4. Retrieve only the data with wind speed in a specific range + +Retrieve only the data where the wind speed is between 5 and 15 miles per hour. \ No newline at end of file diff --git a/exercises/concept/weather-report/.docs/introduction.md b/exercises/concept/weather-report/.docs/introduction.md new file mode 100644 index 00000000..5dd323c9 --- /dev/null +++ b/exercises/concept/weather-report/.docs/introduction.md @@ -0,0 +1,127 @@ +# Introduction + +In SQL, a `SELECT` statement allows you to retrieve data from a database. +The result of a `SELECT` statement is a result set. +A result set contains values arranged in rows and columns. +Each column is a particular attribute of the data. +Each row contains a value for every column. + +One way to think about it is that a set of columns represents a data structure, where each column represents a field of the data structure, and each row represents an instance of the data structure. + +With a `SELECT` statement, you can specify the data you want to retrieve. +You can also optionally transform, filter, and/or modify the shape of the output data. + +## The basics + +The anatomy of a basic `SELECT` statement is as follows: + +```sql +SELECT +FROM +WHERE ; +``` + +~~~~exercism/note +The `FROM` and `WHERE` clauses are optional. +For example, a statement like `SELECT "Hello, world.";` is perfectly valid. + +Also note that the line breaks are not required; any spacing will suffice to separate the different clauses (i.e. parts) of the `SELECT` statement. +~~~~ + +Immediately following the `SELECT` keyword is a list of the columns that you want in the result. +The `FROM` clause identifies the source of the data, which is typically a table in the database. +The `WHERE` clause filters the output data by one or more criteria. + +For example, consider a database with a table named `inventory` containing the following data: + +| upc | category | supplier | brand | product_name | weight | stock | +|--------------|------------|----------------|-------------|----------------------------------|--------|-------| +| 812345670019 | Cookware | KitchenCo | HearthStone | 10" Non-Stick Skillet | 1.8 | 42 | +| 845678120334 | Utensils | HomePro Supply | PrepMaster | Stainless Steel Ladle | 0.4 | 120 | +| 899001234556 | Appliances | Culinary Depot | QuickBrew | Single-Serve Coffee Maker | 4.2 | 18 | +| 823450987112 | Cookware | KitchenCo | FreshKeep | 12-Piece Glass Container Set | 6 | 33 | +| 867530900221 | Utensils | HomePro Supply | EdgeCraft | 8' Chef's Knife | 0.6 | 27 | +| 880012349876 | Appliances | Culinary Depot | HeatWave | Compact Toaster Oven | 7.5 | 14 | +| 833221109443 | Utensils | HomePro Supply | PureScrub | Heavy-Duty Kitchen Sponge (3-pk) | 0.2 | 200 | +| 899998877665 | Cookware | KitchenCo | IronCraft | Cast-Iron Grill Pan | 5.3 | 21 | +| 844110220987 | Appliances | Culinary Depot | BlendPro | High-Speed Personal Blender | 3.1 | 16 | + +If we want to retrieve all of the data from the table, we could run the following query: + +```sql +SELECT * FROM inventory; +``` + +Result: + +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- ----------- -------------------------------- ------ ----- +812345670019 Cookware KitchenCo HearthStone 10" Non-Stick Skillet 1.8 42 +845678120334 Utensils HomePro Supply PrepMaster Stainless Steel Ladle 0.4 120 +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +823450987112 Cookware KitchenCo FreshKeep 12-Piece Glass Container Set 6 33 +867530900221 Utensils HomePro Supply EdgeCraft 8' Chef's Knife 0.6 27 +880012349876 Appliances Culinary Depot HeatWave Compact Toaster Oven 7.5 14 +833221109443 Utensils HomePro Supply PureScrub Heavy-Duty Kitchen Sponge (3-pk) 0.2 200 +899998877665 Cookware KitchenCo IronCraft Cast-Iron Grill Pan 5.3 21 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` + +If we only want the category and product_name values, we could specify those columns: + +```sql +SELECT category, product_name FROM inventory; +``` + +Result: + +``` +category product_name +---------- -------------------------------- +Cookware 10" Non-Stick Skillet +Utensils Stainless Steel Ladle +Appliances Single-Serve Coffee Maker +Cookware 12-Piece Glass Container Set +Utensils 8' Chef's Knife +Appliances Compact Toaster Oven +Utensils Heavy-Duty Kitchen Sponge (3-pk) +Cookware Cast-Iron Grill Pan +Appliances High-Speed Personal Blender +``` + +## Filtering data with the WHERE clause + +The `WHERE` clause allows you to filter the data retrieved by a `SELECT` statement. +For example, if we only want Appliances, we can do the following: + +```sql +SELECT * FROM inventory +WHERE category = "Appliances"; +``` + +Result: +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- --------- --------------------------- ------ ----- +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +880012349876 Appliances Culinary Depot HeatWave Compact Toaster Oven 7.5 14 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` + +Or maybe we only want data where the weight is between 2.0 and 6.0: + +```sql +SELECT * FROM inventory +WHERE weight BETWEEN 2.0 AND 6.0; +``` + +Result: +``` +upc category supplier brand product_name weight stock +------------ ---------- -------------- --------- ---------------------------- ------ ----- +899001234556 Appliances Culinary Depot QuickBrew Single-Serve Coffee Maker 4.2 18 +823450987112 Cookware KitchenCo FreshKeep 12-Piece Glass Container Set 6 33 +899998877665 Cookware KitchenCo IronCraft Cast-Iron Grill Pan 5.3 21 +844110220987 Appliances Culinary Depot BlendPro High-Speed Personal Blender 3.1 16 +``` diff --git a/exercises/concept/weather-report/.meta/config.json b/exercises/concept/weather-report/.meta/config.json new file mode 100644 index 00000000..bffa305b --- /dev/null +++ b/exercises/concept/weather-report/.meta/config.json @@ -0,0 +1,21 @@ +{ + "authors": [ + "blackk-foxx" + ], + "contributors": [ + "IsaacG", + "jimmytty" + ], + "files": { + "exemplar": [ + ".meta/exemplar.sql" + ], + "solution": [ + "weather-report.sql" + ], + "test": [ + "weather-report_test.sql" + ] + }, + "blurb": "Learn SELECT statement basics" +} diff --git a/exercises/concept/weather-report/.meta/design.md b/exercises/concept/weather-report/.meta/design.md new file mode 100644 index 00000000..9c755b9e --- /dev/null +++ b/exercises/concept/weather-report/.meta/design.md @@ -0,0 +1,20 @@ +# Design + +## Goal + +The goal of this exercise is to teach students the basics of the `SELECT` statement. + +## Learning objectives + +- Know the purpose of the `SELECT` statement. +- Be able to select specific columns from a table. +- Be able to do basic filtering using the `WHERE` clause. + +## Out of scope + +- Advanced filtering +` Subqueries + +## Concepts + +- `select` diff --git a/exercises/concept/weather-report/.meta/exemplar.sql b/exercises/concept/weather-report/.meta/exemplar.sql new file mode 100644 index 00000000..f652fe5e --- /dev/null +++ b/exercises/concept/weather-report/.meta/exemplar.sql @@ -0,0 +1,21 @@ +CREATE TABLE all_data AS + -- Task 1. Select all records. + SELECT * FROM weather_readings +; + +CREATE TABLE location_and_temperature AS + -- Task 2. Select only location and temperature data. + SELECT location, temperature FROM weather_readings +; + +CREATE TABLE seattle AS + -- Task 3. Select all data for Seattle. + SELECT * FROM weather_readings + WHERE location = "Seattle" +; + +CREATE TABLE limited_wind_speed AS + -- Task 4. Select all data where the wind speed is between 5 and 15 miles per hour. + SELECT * FROM weather_readings + WHERE wind_speed BETWEEN 5 AND 15 +; diff --git a/exercises/concept/weather-report/create_fixture.sql b/exercises/concept/weather-report/create_fixture.sql new file mode 100644 index 00000000..f13b663d --- /dev/null +++ b/exercises/concept/weather-report/create_fixture.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS weather_readings; +CREATE TABLE weather_readings ( + date TEXT NOT NULL, + location TEXT NOT NULL, + temperature INTEGER NOT NULL, + wind_speed INTEGER NOT NULL +); + +.mode csv +.import ./data.csv weather_readings diff --git a/exercises/concept/weather-report/data.csv b/exercises/concept/weather-report/data.csv new file mode 100644 index 00000000..d01fb5e2 --- /dev/null +++ b/exercises/concept/weather-report/data.csv @@ -0,0 +1,6 @@ +"2025-10-22","Portland",53,19 +"2025-10-22","Seattle",56,5 +"2025-10-22","Boise",60,1 +"2025-10-23","Portland",54,11 +"2025-10-23","Seattle",57,6 +"2025-10-23","Boise",62,21 diff --git a/exercises/concept/weather-report/report-results b/exercises/concept/weather-report/report-results new file mode 100644 index 00000000..70e2be0c --- /dev/null +++ b/exercises/concept/weather-report/report-results @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +db_file=$1 +mapfile -t slugs < <(jq -r 'keys[]' test_data.json) + +# Generate result for each test +for slug in "${slugs[@]}"; do + actual=$(sqlite3 -json "$db_file" "SELECT * FROM ${slug};") + if [[ -z "$actual" ]]; then + actual="[]" + fi + jq -n --slurpfile test_data test_data.json --argjson got "${actual}" --arg slug "${slug}" -f test-result.jq +done > results.txt + +# Aggregate results +jq -n --slurpfile results results.txt '$results' > output.json diff --git a/exercises/concept/weather-report/test-result.jq b/exercises/concept/weather-report/test-result.jq new file mode 100644 index 00000000..4686e6d2 --- /dev/null +++ b/exercises/concept/weather-report/test-result.jq @@ -0,0 +1,26 @@ +def columns: + if (. | length) == 0 then [] + else .[0] | keys + end; + +def rows: + map(to_entries | map(.value)); + +def failure_message(got; expected): + (got | columns | tostring) as $got_columns + | (expected | columns | tostring) as $expected_columns + | if $got_columns != $expected_columns then + "Expected columns \($expected_columns); but got \($got_columns)" + else + (got | rows | tostring) as $got_rows + | (expected | rows | tostring) as $expected_rows + | "With columns \($got_columns)\nexpected rows \($expected_rows)\nbut got \($got_rows)" + end; + +$test_data[0][$slug] +| del(.expected) as $entry +| if $got != .expected then + $entry + {"status": "fail", "message": failure_message($got; .expected)} + else + $entry + {"status": "pass"} + end diff --git a/exercises/concept/weather-report/test_data.json b/exercises/concept/weather-report/test_data.json new file mode 100644 index 00000000..bf82133f --- /dev/null +++ b/exercises/concept/weather-report/test_data.json @@ -0,0 +1,43 @@ +{ + "all_data": { + "task_id": 1, + "description": "All data", + "expected": [ + {"date": "2025-10-22", "location": "Portland", "temperature": 53, "wind_speed": 19}, + {"date": "2025-10-22", "location": "Seattle", "temperature": 56, "wind_speed": 5}, + {"date": "2025-10-22", "location": "Boise", "temperature": 60, "wind_speed": 1}, + {"date": "2025-10-23", "location": "Portland", "temperature": 54, "wind_speed": 11}, + {"date": "2025-10-23", "location": "Seattle", "temperature": 57, "wind_speed": 6}, + {"date": "2025-10-23", "location": "Boise", "temperature": 62, "wind_speed": 21} + ] + }, + "location_and_temperature": { + "task_id": 2, + "description": "Just location and temperature", + "expected": [ + {"location": "Portland", "temperature": 53}, + {"location": "Seattle", "temperature": 56}, + {"location": "Boise", "temperature": 60}, + {"location": "Portland", "temperature": 54}, + {"location": "Seattle", "temperature": 57}, + {"location": "Boise", "temperature": 62} + ] + }, + "seattle": { + "task_id": 3, + "description": "Seattle only", + "expected": [ + {"date": "2025-10-22", "location": "Seattle", "temperature": 56, "wind_speed": 5}, + {"date": "2025-10-23", "location": "Seattle", "temperature": 57, "wind_speed": 6} + ] + }, + "limited_wind_speed": { + "task_id": 4, + "description": "wind_speed within range", + "expected": [ + {"date": "2025-10-22", "location": "Seattle", "temperature": 56, "wind_speed": 5}, + {"date": "2025-10-23", "location": "Portland", "temperature": 54, "wind_speed": 11}, + {"date": "2025-10-23", "location": "Seattle", "temperature": 57, "wind_speed": 6} + ] + } +} diff --git a/exercises/concept/weather-report/weather-report.sql b/exercises/concept/weather-report/weather-report.sql new file mode 100644 index 00000000..5fc7f875 --- /dev/null +++ b/exercises/concept/weather-report/weather-report.sql @@ -0,0 +1,19 @@ +CREATE TABLE all_data AS + -- Task 1. Select all records. + SELECT "TODO: Replace this SELECT statement as needed to accomplish the task" +; + +CREATE TABLE location_and_temperature AS + -- Task 2. Select only location and temperature data. + SELECT "TODO: Replace this SELECT statement as needed to accomplish the task" +; + +CREATE TABLE seattle AS + -- Task 3. Select all data for Seattle. + SELECT "TODO: Replace this SELECT statement as needed to accomplish the task" +; + +CREATE TABLE limited_wind_speed AS + -- Task 4. Select all data where the wind speed is between 5 and 15 miles per hour. + SELECT "TODO: Replace this SELECT statement as needed to accomplish the task" +; diff --git a/exercises/concept/weather-report/weather-report_test.sql b/exercises/concept/weather-report/weather-report_test.sql new file mode 100644 index 00000000..0951bc63 --- /dev/null +++ b/exercises/concept/weather-report/weather-report_test.sql @@ -0,0 +1,14 @@ +-- Create database: +.read ./create_fixture.sql + +-- Run user solution and store results +.mode markdown +.output user_output.md +.read ./weather-report.sql +.save ./results.db + +.output + +-- Report results +.shell bash ./report-results results.db +.shell rm -f ./results.db