├── .gitignore
├── html_version
├── glossary_index.json
├── gitbook
│ ├── images
│ │ ├── favicon.ico
│ │ └── apple-touch-icon-precomposed-152.png
│ ├── fonts
│ │ ├── opensans
│ │ │ ├── 300.woff
│ │ │ ├── 300i.woff
│ │ │ ├── 400.woff
│ │ │ ├── 400i.woff
│ │ │ ├── 600.woff
│ │ │ ├── 600i.woff
│ │ │ ├── 700.woff
│ │ │ └── 700i.woff
│ │ ├── merriweather
│ │ │ ├── 250.woff
│ │ │ ├── 400.woff
│ │ │ ├── 700.woff
│ │ │ ├── 900.woff
│ │ │ ├── 250i.woff
│ │ │ ├── 400i.woff
│ │ │ ├── 700i.woff
│ │ │ └── 900i.woff
│ │ └── fontawesome
│ │ │ ├── FontAwesome.otf
│ │ │ ├── fontawesome-webfont.eot
│ │ │ ├── fontawesome-webfont.ttf
│ │ │ └── fontawesome-webfont.woff
│ ├── plugins
│ │ └── gitbook-plugin-mathjax
│ │ │ └── plugin.js
│ ├── print.css
│ └── style.css
├── search_index.json
├── GLOSSARY.html
└── index.html
├── cover_small.jpg
├── GLOSSARY.md
├── basic_syntax
└── README.md
├── aggregation
├── README.md
├── aggregation_clauses.md
└── aggregation_functions.md
├── SUMMARY.md
├── data_modification_statements
├── update_commands.md
├── insert_commands.md
├── delete_commands.md
└── README.md
├── subqueries_in_the_where_clause
├── README.md
└── using_operators_in_a_subquery.md
├── the_join_family_operators
├── README.md
├── outer_join.md
├── natural_join.md
└── the_inner_join_operator.md
├── README.md
├── subqueries_in_the_from_&_select_clause
└── README.md
├── table_variables_&_set_operators
└── README.md
└── basic_select_statements
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
--------------------------------------------------------------------------------
/html_version/glossary_index.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/cover_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/cover_small.jpg
--------------------------------------------------------------------------------
/html_version/gitbook/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/images/favicon.ico
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/opensans/300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/opensans/300.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/opensans/300i.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/opensans/300i.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/opensans/400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/opensans/400.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/opensans/400i.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/opensans/400i.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/opensans/600.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/opensans/600.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/opensans/600i.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/opensans/600i.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/opensans/700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/opensans/700.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/opensans/700i.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/opensans/700i.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/merriweather/250.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/merriweather/250.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/merriweather/400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/merriweather/400.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/merriweather/700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/merriweather/700.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/merriweather/900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/merriweather/900.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/merriweather/250i.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/merriweather/250i.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/merriweather/400i.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/merriweather/400i.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/merriweather/700i.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/merriweather/700i.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/merriweather/900i.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/merriweather/900i.woff
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/fontawesome/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/fontawesome/FontAwesome.otf
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/fontawesome/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/fontawesome/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/fontawesome/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/fontawesome/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/html_version/gitbook/fonts/fontawesome/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/fonts/fontawesome/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/html_version/gitbook/images/apple-touch-icon-precomposed-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgducharme/SQL-Basics/HEAD/html_version/gitbook/images/apple-touch-icon-precomposed-152.png
--------------------------------------------------------------------------------
/GLOSSARY.md:
--------------------------------------------------------------------------------
1 | ## Data Definition Language (DDL)
2 |
3 | Includes commands to create and/or drop a table or database.
4 |
5 | ## Data Manipulation Language (DML)
6 |
7 | Includes commands to query and modify databases.
8 |
--------------------------------------------------------------------------------
/html_version/gitbook/plugins/gitbook-plugin-mathjax/plugin.js:
--------------------------------------------------------------------------------
1 | require(["gitbook"], function(gitbook) {
2 | MathJax.Hub.Config({
3 | tex2jax: {
4 | processEscapes: true
5 | }
6 | });
7 |
8 |
9 | gitbook.events.bind("page.change", function() {
10 | MathJax.Hub.Typeset()
11 | });
12 | });
13 |
14 |
--------------------------------------------------------------------------------
/html_version/search_index.json:
--------------------------------------------------------------------------------
1 | {"version":"0.5.2","fields":[{"name":"title","boost":10},{"name":"body","boost":1}],"ref":"url","documentStore":{"store":{"index.html#gitbook_4":["book","welcom"]},"length":1},"tokenStore":{"root":{"docs":{},"b":{"docs":{},"o":{"docs":{},"o":{"docs":{},"k":{"docs":{"index.html#gitbook_4":{"ref":"index.html#gitbook_4","tf":10.666666666666666}}}}}},"w":{"docs":{},"e":{"docs":{},"l":{"docs":{},"c":{"docs":{},"o":{"docs":{},"m":{"docs":{"index.html#gitbook_4":{"ref":"index.html#gitbook_4","tf":0.3333333333333333}}}}}}}}},"length":2},"corpusTokens":["book","welcom"],"pipeline":["trimmer","stopWordFilter","stemmer"]}
--------------------------------------------------------------------------------
/basic_syntax/README.md:
--------------------------------------------------------------------------------
1 | # Basic Syntax
2 |
3 |
4 |
5 |
6 | ### What is Structured Query Language?
7 |
8 | Structured Query Language, or SQL, is a special-purpose programming language used to manage data within a relational database management system (RDBMS).
9 |
10 | You will find that there are multiple ways to write the same query in SQL, and some ways are better than others.
11 |
12 |
13 |
14 | ### Two Parts of SQL
15 |
16 | **Data Definition Language (DDL):** DDL includes commands to create a table, to drop a table, or create and drop other aspects of a database.
17 |
18 | **Data Manipulation Language (DML):** DML includes commands that are used to query and modify a database. It includes the select statement for querying the database, and the insert, update, and delete statements, all for modifying the database.
19 |
--------------------------------------------------------------------------------
/aggregation/README.md:
--------------------------------------------------------------------------------
1 | # Aggregation
2 |
3 |
4 |
5 |
6 | ### Aggregation Functions
7 |
8 | The aggregate, or aggregation functions, initially appear inside the `SELECT` clause of a query, and they perform computations over sets of values in multiple rows of our relations. The basic aggregation functions supported by every SQL systems are: `MIN`, `MAX`, `SUM`, `AVG`, and `COUNT`.
9 |
10 |
11 |
12 | ### Two New Clauses
13 |
14 | Now that the aggregation functions have been introduced, two new clauses can be added to the SQL select statements. These are the: `GROUP BY`, and the `HAVING` clauses.
15 | * The `GROUP BY` allows us to partition our relations into groups, and then compute aggregated aggregate functions over each group independently.
16 | * The `HAVING` condition allows us to test filters on the results of aggregate values.
17 | * The difference between the `WHERE` and `HAVING` conditions is the `HAVING` applies to all the groups generated from the `GROUP BY` clause. While the `WHERE` condition applies to single rows at a time.
18 |
19 | The syntax looks like this:
20 |
21 | ```sql
22 | SELECT A1, A2, . . . , A(n)
23 | FROM R1, R2, . . . , R(m)
24 | WHERE
25 | GROUP BY
26 | HAVING ;
27 | ```
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | * [Introduction](README.md)
4 | * [Basic Syntax](basic_syntax/README.md)
5 | * [Basic Select Statements](basic_select_statements/README.md)
6 | * [Table Variables & Set Operators](table_variables_&_set_operators/README.md)
7 | * [Subqueries in the Where Clause](subqueries_in_the_where_clause/README.md)
8 | * [Using Operators in a Subquery](subqueries_in_the_where_clause/using_operators_in_a_subquery.md)
9 | * [Subqueries in the From & Select Clause](subqueries_in_the_from_&_select_clause/README.md)
10 | * [The 'Join' Family Operators](the_join_family_operators/README.md)
11 | * [Inner Join](the_join_family_operators/the_inner_join_operator.md)
12 | * [Natural Join](the_join_family_operators/natural_join.md)
13 | * [Outer Join](the_join_family_operators/outer_join.md)
14 | * [Aggregation](aggregation/README.md)
15 | * [Aggregation Functions](aggregation/aggregation_functions.md)
16 | * [Aggregation Clauses](aggregation/aggregation_clauses.md)
17 | * [Data Modification Statements](data_modification_statements/README.md)
18 | * [Insert Commands](data_modification_statements/insert_commands.md)
19 | * [Delete Commands](data_modification_statements/delete_commands.md)
20 | * [Update Commands](data_modification_statements/update_commands.md)
21 |
22 |
--------------------------------------------------------------------------------
/data_modification_statements/update_commands.md:
--------------------------------------------------------------------------------
1 | # Update Commands
2 |
3 |
4 |
5 |
6 | Let's find all users who do not currently have a `ratingDate` assigned to one of their rating's, and let's assign it a value.
7 |
8 | Our query will look like this:
9 |
10 | ```sql
11 | SELECT *
12 | FROM User
13 | WHERE uID in (SELECT uID FROM Review WHERE ISNULL ratingDate);
14 | ```
15 |
16 | The query is going to look in the `User` relation and for each individual user, it will check for their `uID` in the `Review` table, and if the `ratingDate` returns true for `ISNULL`, then it will return that user in the end result.
17 |
18 | If we ran the query, our results would include the users "Darrel Sherman", and "Chris Anderson", with a `uID` of 207 and 202 respectively.
19 |
20 | Well now we want to update the `ratingDate` for these two individuals in the `Review` table. We would have to edit our query a little bit and have it look like this:
21 |
22 | ```sql
23 | UPDATE Review
24 | SET ratingDate = '2014'
25 | WHERE uID in (SELECT uID FROM Review WHERE ISNULL ratingDate) and ISNULL ratingDate;
26 | ```
27 |
28 | We added the `UPDATE` statement, and we're telling SQL to `UPDATE` the `Review` table. Find all the users with a `uID` that satisfy the subquery in the `WHERE` clause, but only consider reviews that currently have no `ratingDate`. Then take the `ratingDate` for those reviews and give it a value of `'2014'`. We'll assume we don't know the exact date that they rated the movie, but we know it was in 2014.
29 |
--------------------------------------------------------------------------------
/subqueries_in_the_where_clause/README.md:
--------------------------------------------------------------------------------
1 | # Subqueries in the Where Clause
2 |
3 |
4 |
5 |
6 | ### Basic Syntax
7 |
8 | Just like before, our queries will contain a `SELECT` clause, a `FROM` clause, and a `WHERE` clause specifying a condition. However, we now are adding in the ability to nest a `SELECT` clause inside the `WHERE` clause, thus creating a subquery.
9 |
10 | Subqueries can be very powerful when trying to eliminate duplicates, and is often more efficient than using joining relations.
11 |
12 |
13 |
14 | ### Creating a Basic Subquery
15 |
16 | Let's create a query that looks for a movie's ID, title, and director, but only if it has a rating above 4.
17 |
18 | We can create a sub-query like so:
19 |
20 | ```sql
21 | SELECT DISTINCT Movie.mID, Title, Director
22 | FROM Movie, Review
23 | WHERE Movie.mID in (SELECT mID FROM Review WHERE Rating > 4);
24 | ```
25 |
26 | We could easily do this query without implementing a subquery by joining the Movie relation with the Review relation. However, this is just to show how a subquery would be performed.
27 |
28 | We would then get the movies: *Titanic*, and *Gravity*.
29 |
30 |
31 |
32 | ### Slightly More Complex Subqueries
33 |
34 | Lets create a query that retrieves the `Title` of all movies which have a `Rating` less than 3, and have a `mID` greater than 103.
35 |
36 | Our query would look like this:
37 |
38 | ```sql
39 | SELECT Title
40 | FROM Movie
41 | WHERE mID in (SELECT mID FROM Review WHERE Rating < 3)
42 | AND mID NOT IN (SELECT mID FROM Review WHERE mID < 103);
43 | ```
44 |
45 | Our outside query returns the `Title` of all movies whose `mID` is in the first subquery, but not in the second subquery. Our first subquery looks for all `mID`'s whose `Rating` is less than 3, and the second subquery looks for all `mID`s that are greater than 103.
46 |
47 | The output movies would be: *Spiderman*, *Gravity*, and *Harry Potter*.
48 |
--------------------------------------------------------------------------------
/the_join_family_operators/README.md:
--------------------------------------------------------------------------------
1 | # The 'Join' Family Operators
2 |
3 |
4 |
5 |
6 | ### The Basics
7 |
8 | In our select statements, we seperate tables in the `FROM` clause by commas, and that is implicitly a cross product of those tables.
9 |
10 | Like so:
11 |
12 | ```sql
13 | SELECT A1, A2, . . . , A(n)
14 | FROM R1, R2, . . . , R(m)
15 | WHERE ;
16 | ```
17 |
18 | However, there is a way to explicitly join two or more tables using one of the `JOIN` operators. There are a few different types, and they are listed below:
19 |
20 | 1. The `INNER JOIN` on *condition*
21 | * This kind of join operator takes the cross product of the tables and then applies a condition, and only taking the cross product elements that satisfy the condition given. It then eliminates all duplicate columns that are created.
22 | 2. The `NATURAL JOIN`
23 | * The `NATURAL JOIN` operator equates all columns with the same name in the tables that are being joined. It requires the values in the columns to be the same in order to keep the elements in the cross product. This type of join also eliminates any duplicate columns that are created.
24 | 3. The `INNER JOIN USING(attrs)`
25 | * This again is an `INNER JOIN`, however this type of join takes a special clause called `USING` and listing attributes. This is sort of like the `NATURAL JOIN`, except you specifically state the attributes that you want to be equated.
26 | 4. The `OUTER JOIN`
27 | * There are multiple forms of this kind of join operator. There is the `LEFT OUTER JOIN`, the `RIGHT OUTER JOIN`, and the `FULL OUTER JOIN`. These joins combine elements similar to the `INNER JOIN`, except when elements don't match the `INNER JOIN` condition, they're still added to the result and padded with `` values.
28 |
29 |
30 | All of these join operators don't add any specific power to SQL, they can all be described using different constructs, however they can be very helpful when creating queries. Especially the `OUTER JOIN`, for it is very difficult to express without the `OUTER JOIN` itself.
31 |
--------------------------------------------------------------------------------
/aggregation/aggregation_clauses.md:
--------------------------------------------------------------------------------
1 | # Aggregation Clauses
2 |
3 |
4 |
5 |
6 | ### The `GROUP BY` Clause
7 |
8 | The `GROUP BY` clause is only used in conjuction with aggregation. Our first query is going to find the number of movies that were produced in each year, and it's going to do so by using grouping. Essentially what grouping does is it takes a relation and it partitions it by values of a given attribute or set of attributes.
9 |
10 | ```sql
11 | SELECT Year, COUNT(*)
12 | FROM Movie
13 | GROUP BY Year;
14 | ```
15 |
16 | Specifically in this query we're taking the `Movie` relation and we're breaking it into multiple groups. Each group is represented by each individual year. Then for each group we return one tuple in the result containing the `Year` for the group and the number of tuples in the group.
17 |
18 | We would then get the number 1 for each year, because there is no two movies in our database that were produced in the same year.
19 |
20 |
21 |
22 | ### The `HAVING` Clause
23 |
24 | The `HAVING` clause is another clause that is only used with aggregation. The `HAVING` clause allows us to apply conditions to the results of the aggregate functions. The `HAVING` clause is placed after the `GROUP BY` clause and it allows us to check conditions that involve the entire group. In contrast, the `WHERE` clause applies only to one tuple at a time.
25 |
26 | Let's create a query that finds directors which have produced more than one movie.
27 |
28 | Our query will look like this:
29 |
30 | ```sql
31 | SELECT Director
32 | FROM Movie
33 | GROUP BY Director
34 | HAVING COUNT(DISTINCT mID) > 1;
35 | ```
36 |
37 | The above query is going to get each `Director` from the `Movie` table, and then put them into their own groups. For each group, or `Director`, it is going to check to see if there are more than one `mID`'s that are associated with that `Director`. If there is, the `Director` will be returned in the results. If not, then the `Director` will not be returned.
38 |
39 | For this particular query, we would either get an error or a `null` value, because there is no director in our database that has produced more than one movie.
40 |
--------------------------------------------------------------------------------
/data_modification_statements/insert_commands.md:
--------------------------------------------------------------------------------
1 | # Insert Commands
2 |
3 |
4 |
5 |
6 | Let's assume that we want to insert a new movie into our database. We do this by saying we want to `INSERT INTO Movie`, we use the keyword values and we simply list the values we want to insert.
7 |
8 | Like so:
9 |
10 | ```sql
11 | INSERT INTO Movie VALUES(109, 'Cinderella', 1950);
12 | ```
13 |
14 | In this query we are inserting values for the attributes of the `Movie` table. We included a `mID`, `Title`, and `Year`. We did not include a `Director`, so thus there will be a `null` value in the database for that attribute of Cinderella.
15 |
16 | Now let's do a little more complicated insert command. Now that we have *Cinderella* in our database, lets add a few users into the `Review` table and have them rate the new movie. We're going to start by inserting two new users into the `User` table.
17 |
18 | Like so:
19 |
20 | ```sql
21 | INSERT INTO Review VALUES(209, 'Jonathan Murleau')
22 | INSERT INTO Review VALUES(210, 'Barabara Vance');
23 | ```
24 |
25 | We now have two new users but they have not yet rated on any movies, so let's have them rate on our new movie *Cinderella*.
26 |
27 | We now want to return all users where there `mID` does not appear in the `Review` table. Like so:
28 |
29 | ```sql
30 | SELECT *
31 | FROM User
32 | WHERE uID NOT IN (SELECT uID FROM Review);
33 | ```
34 |
35 | Our query would be the result of the two users that we just inserted: Jonathan and Barbara. Well now that we have singled out the users who have not rated yet, lets insert those users into the `Review` table with the correct schema.
36 |
37 | Like this:
38 |
39 | ```sql
40 | INSERT INTO Review
41 | SELECT uID, 109, 3, null
42 | FROM User
43 | WHERE uID NOT IN (SELECT uID FROM Review);
44 | ```
45 |
46 | This query is saying to select all users who do not already appear in the `Review` table. We're going to take these users and we're going to select their `uID`, then we are going to assign them the correct values for all of the `Review` attributes. As a reminder, the `Review` table has the attributes: `uID`, `mID`, `Rating`, and `ratingDate`. So in our query we are selecting their `uID`, then having the rate the `mID` of 109 (which is the movie *Cinderella*), they both are going to rate the movie with a 3, and we inserted a `null` value for the `ratingDate`. Lastly, we are going to take this end result, and `INSERT INTO` the `Review` table.
47 |
--------------------------------------------------------------------------------
/data_modification_statements/delete_commands.md:
--------------------------------------------------------------------------------
1 | # Delete Commands
2 |
3 |
4 |
5 |
6 | Let's create a query that finds all users who rated more than 2 movies. Let's assume that users are only allowed to rate 2 movies, and no more.
7 |
8 | Our query would look like this:
9 |
10 | ```sql
11 | SELECT uID, COUNT(DISTINCT Rating)
12 | FROM Review
13 | GROUP BY uID
14 | HAVING COUNT(DISTINCT Rating) > 2;
15 | ```
16 |
17 | This query says to go into the `Review` relation, then form groups or partitions by each user ID. This allows us to evaluate the set of ratings for each individual `User`. We're going to count how many `DISTINCT` `Rating`s there are in each group (or for each user). Then it's going to check to see if that number is greater than two, and if it is, it's going to return the `uID` of that user, and also the number of `Rating`s that user has given.
18 |
19 | If we were to run the query we would return the user: "Darrel Sherman", who has a `uID` of 207. He is the only person to have gone over his rating limit, and has rated 3 movies. Since he has broken the hypothetical contract, we are going to have to delete him from the database.
20 |
21 | Our query would look like this:
22 |
23 | ```sql
24 | DELETE FROM Review
25 | WHERE uID in
26 | (SELECT uID, COUNT(DISTINCT Rating)
27 | FROM Review
28 | GROUP BY uID
29 | HAVING COUNT(DISTINCT Rating) > 2);
30 | ```
31 |
32 | So all we did was add the `DELETE FROM
WHERE ` statement, and turned our previous query into a subquery in the `WHERE` clause. The query is saying to return all the users who have rated more than 2 movies (just like before), then `DELETE` those users from the `Review` relation.
33 |
34 | If we were to run the query, we would delete all instances of the `uID` 207, or Darrel Sherman, from the `Review` relation. However, we would NOT delete him from the `User` relation. In order to do that we would just have to change the relation to `DELETE FROM`.
35 |
36 | Like so:
37 |
38 | ```sql
39 | DELETE FROM User
40 | WHERE uID in
41 | (SELECT uID, COUNT(DISTINCT Rating)
42 | FROM Review
43 | GROUP BY uID
44 | HAVING COUNT(DISTINCT Rating) > 2);
45 | ```
46 |
47 | We did the exact same query before, except change the table from `Review` to `User`. Now some SQL database systems don't allow you to delete data if the subquery includes the same relation that you are deleting from, so it can get a little tricky depending on the database you are using.
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SQL Basics
2 |
3 |
4 |
5 | **What This Book is About**
6 |
7 | This book will cover the basics of SQL, and should help introduce beginners to SQL concepts. It is also a good documentation source when forgetting how the basic SQL syntax works.
8 |
9 | **Contributing**
10 |
11 | This book is open source, so please feel free to visit [the github repository](https://github.com/hgducharme/SQL-Basics) to help contribute! If you notice any typos or errors in this book, you can clone the repo and open a pull request with the new and improved changes, or simply just open a new issue. Any contribution is greatly appreciated and it will help make this book better for those reading it after you!
12 |
13 | **License**
14 |
15 | This book is currently licensed under a Creative Commons license. For more information, read more on [the official Creative Commons website](http://creativecommons.org/licenses/by-nc-sa/4.0/).
16 |
17 |
18 | ---
19 |
20 |
21 | **Here is the example database that will be used throughout the book:**
22 |
23 |
24 |
25 | **Movies**
26 |
27 | | mID | Title | Year | Director |
28 | | --- | ------------- | ---- | --------------- |
29 | | 101 | Top Gun | 1986 | Tony Scott |
30 | | 102 | Titanic | 1997 | James Cameron |
31 | | 103 | The Lion King | 1994 | Rob Minkoff |
32 | | 104 | Gravity | 2013 | Alfonso Cuaron |
33 | | 105 | Harry Potter | 2001 | `` |
34 | | 106 | Cast Away | 2000 | Robert Zemeckis |
35 | | 107 | Spider Man | 2002 | Sam Raimi |
36 | | 108 | The Godfather | 1972 | Francis Coppola |
37 |
38 |
39 |
40 | **User**
41 |
42 | | uID | Name |
43 | | --- | ---------------- |
44 | | 201 | James Dean |
45 | | 202 | Chris Anderson |
46 | | 203 | Ashley Burley |
47 | | 204 | Ralph Truman |
48 | | 205 | Gordon Maximus |
49 | | 206 | Sarah Rodgriguez |
50 | | 207 | Darrel Sherman |
51 | | 208 | Lisa Jackson |
52 |
53 |
54 |
55 | **Review**
56 |
57 | | uID | mID | Rating | ratingDate |
58 | | --- | --- | ------ | ---------- |
59 | | 201 | 101 | 2 | 2014-03-09 |
60 | | 201 | 101 | 4 | 2014-03-02 |
61 | | 202 | 104 | 4 | `` |
62 | | 203 | 107 | 2 | 2014-03-24 |
63 | | 204 | 103 | 4 | 2014-03-17 |
64 | | 204 | 104 | 2 | 2014-03-13 |
65 | | 205 | 108 | 3 | 2014-03-24 |
66 | | 206 | 102 | 3 | 2014-03-02 |
67 | | 207 | 104 | 5 | `` |
68 | | 207 | 106 | 4 | 2014-03-07 |
69 | | 207 | 102 | 5 | 2014-03-26 |
70 | | 208 | 105 | 2 | 2014-03-13 |
71 |
--------------------------------------------------------------------------------
/data_modification_statements/README.md:
--------------------------------------------------------------------------------
1 | # Data Modification Statements
2 |
3 |
4 |
5 |
6 | ### Inserting Data
7 |
8 | In SQL, there are statements for inserting data, deleting data, and modifying data in a database. For inserting data, there are two methods:
9 |
10 | ```sql
11 | INSERT INTO
12 | VALUES(A1, A2, . . ., An);
13 | ```
14 |
15 | The first method allows us to insert one tuple into the database by specifying its actual value. The command above is saying to `INSERT INTO` a table, then specify the value of that tuple, and the result of the command will be to insert one new tuple into that table with the specified value.
16 |
17 | The other method of inserting data into a table is to run a query over the database as a select statement. That select statement will produce a set of tuples, and as long as that set of tuples has the same schema as the table, we could insert all of the tuples into the table.
18 |
19 | Like this:
20 |
21 | ```sql
22 | INSERT INTO
23 | SELECT STATEMENT;
24 | ```
25 |
26 |
27 |
28 | ### Deleting Data
29 |
30 | Deleting data is fairly simple, and looks like this:
31 |
32 | ```sql
33 | DELETE FROM
34 | WHERE ;
35 | ```
36 |
37 | The above query is saying to `DELETE FROM` a table, `WHERE` a certain condition is true, so this condition is similar to the conditions that we see in the select statement. Then every tuple in the table that satisfies the given condition will be deleted.
38 |
39 | This condition can sometimes get fairly complicated, because it can include subqueries, and aggregation over other tables.
40 |
41 |
42 |
43 | ### Updating Data
44 |
45 | Updating data is done through a command similar to the `DELETE FROM` command. It similarly operates on a single table, it then evaluates a condition over each tuple of the table, and when the condition is true, it will modify the tuple.
46 |
47 | It looks like this:
48 |
49 | ```sql
50 | UPDATE
51 | SET =
52 | WHERE ;
53 | ```
54 |
55 | The above query takes an attribute that is specified and reassigns it to have the value that is the result of the expression. The condition can also get fairly complicated, for it can have subqueries and so on. As well as the expression, for it can involve queries over other tables or the same table in the database.
56 |
57 | You can also update multiple attributes in a tuple. You can update any number of attributes simultaneously by evaluating an expression for each, and assigning the result of that expression to the attribute.
58 |
59 | Like so:
60 |
61 | ```sql
62 | UPDATE
63 | SET A1=, A2=, ..., An=
64 | WHERE ;
65 | ```
66 |
--------------------------------------------------------------------------------
/the_join_family_operators/outer_join.md:
--------------------------------------------------------------------------------
1 | # The Outer Join Operator
2 |
3 |
4 |
5 |
6 | ### Basic Query
7 |
8 | Let's start with a query that joins using the `INNER JOIN` operator which will join `Movie` and `Review` on the matching movie IDs, and will return a few attributes.
9 |
10 | Like so:
11 |
12 | ```sql
13 | SELECT Movie.mID, Title, Rating, ratingDate
14 | FROM Movie INNER JOIN Review USING(mID);
15 | ```
16 |
17 | Now let's assume that we want results with movies that *do not* have a rating date. That is, there is a `` value for that particular element.
18 |
19 | Our query would look like this:
20 |
21 | ```sql
22 | SELECT Movie.mID, Title, Rating, ratingDate
23 | FROM Movie RIGHT OUTER JOIN Review USING(mID);
24 | ```
25 |
26 | Notice that we changed the `INNER JOIN` to a `RIGHT OUTER JOIN` operator. We would get our exact same results as before, which would be table with all the movies and some of their data, such as `Rating` and `ratingDate`. What the `RIGHT OUTER JOIN` operator does is that it takes the tuples on the right side of the relation, and if they don't have a matching tuple on the left then it's still added to the results and padded with `null` values. When there is a tuple on the right with no matching tuple on the left side of the relation, that is called a dangling tuple, and the `RIGHT OUTER JOIN` includes all dangling tuples in its results.
27 |
28 | You can also abbreviate the `RIGHT OUTER JOIN` to just ` JOIN` and it will produce the same results. On top of that, the `OUTER` join can also be combined with the `NATURAL JOIN` by joining relations like this: `NATURAL OUTER JOIN`.
29 |
30 | In our previous query, we checked to see if a tuple in the `Review` table matched the tuple in the `Movie` table. Now what if we wanted to do it the other way around? For example, check to see if a tuple in the `Movie` table matches a tuple in the `Review` table. You might assume that we could just switch the relations around and put `Movie` on the right, and `Review` on the left. However, SQL actually has a counterpart to the `RIGHT OUTER JOIN` operator, and it is the `LEFT OUTER JOIN`.
31 |
32 | It would look like this:
33 |
34 | ```sql
35 | SELECT Movie.mID, Title, Director, Rating
36 | FROM Movie LEFT OUTER JOIN Review USING(mID);
37 | ```
38 |
39 | In the above query we are checking to see if the tuples in the `Movie` table match any tuples in the `Review` table. Instead of checking it the other way around like in our previous query. We are also including the `Director` names in this query, and since the `Director` tuples won't match any tuples in the `Review` table, they will be considered dangling tuples. However, recall that the `OUTER JOIN` operator includes dangling tuples in the result, so no need to worry!
40 |
41 |
42 |
43 | ### The `FULL OUTER JOIN` Operator
44 |
45 | So we know how to include dangling tuples from one relation into our results, but what if we want to include unmatched results from both the left *and* the right side relation? In this case, we use the `FULL OUTER JOIN` operator.
46 |
47 | Let's create another query that includes `null` values from both the `ratingDate` and `Director` columns.
48 |
49 | Our query would look like this:
50 |
51 | ```sql
52 | SELECT Movie.mID, Title, Director, Rating, ratingDate
53 | FROM Movie FULL OUTER JOIN Review USING(mID);
54 | ```
55 |
56 | We would then get a table of results in return with all the values for each column even the ones that are `null`.
57 |
--------------------------------------------------------------------------------
/the_join_family_operators/natural_join.md:
--------------------------------------------------------------------------------
1 | # The Natural Join Operator
2 |
3 |
4 |
5 |
6 | ### Basic `NATURAL JOIN` Query
7 |
8 | Let's use one of our previous queries where we used the `INNER JOIN` to combine the `Movie` and `Review` in order to find the `Rating` that the each movie had.
9 |
10 | It looked like this:
11 |
12 | ```sql
13 | SELECT Title, Rating
14 | FROM Movie INNER JOIN Review
15 | ON Movie.mID = Review.mID;
16 | ```
17 |
18 | As a reminder, the `NATURAL JOIN` operator takes two relations that have column names in common, and then it performs a cross-product that only keeps the tuples where the tuples have the same value in those common attribute names. For example, `Movie` and `Review` have the `mID` column in common. If I were to change the `INNER JOIN` to a `NATURAL JOIN`, they system will automatically apply this equality between the `mID` in the `Movie` relation and the `Review` relation.
19 |
20 | It would look like this:
21 |
22 | ```sql
23 | SELECT Title, Rating
24 | FROM Movie NATURAL JOIN Review;
25 | ```
26 |
27 |
28 |
29 | ### `NATURAL JOIN` with Additional Conditions
30 |
31 | Let's go back to our query using the `INNER JOIN` that finds the movies whose `Rating` is greater than 3, and was produced after the year 1990.
32 |
33 | ```sql
34 | SELECT Title, Rating
35 | FROM Movie JOIN Rating
36 | ON Movie.mID = Review.mID
37 | and Rating > 3 and Year > 1990;
38 | ```
39 |
40 | Now if we changed this to using a `NATURAL JOIN`, it would look like this:
41 |
42 | ```sql
43 | SELECT Title, Rating
44 | FROM Movie NATURAL JOIN Rating
45 | WHERE Rating > 3 and Year > 1990;
46 | ```
47 |
48 | We changed `JOIN` to `NATURAL JOIN`, then deleted the `ON` condition and changed it to a `WHERE` clause. Lastly, we deleted join relation since `NATURAL JOIN` automatically equates columns with the same name.
49 |
50 | We would then get the same movies we got before: *Gravity*, *The Lion King*, *Titanic*, and *Cast Away*.
51 |
52 |
53 |
54 | ### The `USING` Clause
55 |
56 | There is a feature in SQL that goes with the `NATURAL JOIN` operator that is often regarded as better practice than just using `NATURAL JOIN`. That feature is the `USING` clause, and it explicitly lists the attributes that should be equated when joining two relations.
57 |
58 | Using the previous `INNER JOIN` query, it would look like this:
59 |
60 | ```sql
61 | SELECT Title, Rating
62 | FROM Movie JOIN Rating
63 | ON Movie.mID = Review.mID
64 | and Rating > 3 and Year > 1990;
65 | ```
66 |
67 | Now if we changed this to using a `NATURAL JOIN` with `USING`, it would look like this:
68 |
69 | ```sql
70 | SELECT Title, Rating
71 | FROM Movie JOIN Rating USING(mID)
72 | WHERE Rating > 3 and Year > 1990;
73 | ```
74 |
75 | Notice that we deleted `NATURAL` and only kept the word `JOIN`. We then specify that the `mID` is the attribute that should be equated across `Movie` and `Review`.
76 |
77 | We can only put in the `USING` clause any attributes that appear in *both* tables. If we tried to put an attribute that was only in one table, the query would not run and would return an error.
78 |
79 | The reason this is considered better practice is because the `NATURAL JOIN` implicitly joins all columns that have the same name, when this may not be favored. For instance, it's possible to not realize that two relations have the same column name, and then the system will sort-of, under the covers, equate those values. Compared to specificaly stating which relations to join which will prevent the query from equating values that don't need to be equated. Also, in real applications there can often be upwards of 100 attributes in a relationship. Thus, making it more likely that you have attributes with the same name but aren't meant to get equated.
80 |
--------------------------------------------------------------------------------
/subqueries_in_the_from_&_select_clause/README.md:
--------------------------------------------------------------------------------
1 | # Subqueries in the From & Select Clause
2 |
3 |
4 |
5 |
6 | ### What They Are Used For
7 |
8 | * When using subqueries in the `WHERE` clause, the subquery generates a set of elements that will be used in a comparison.
9 | * When using subqueries in the `FROM` clause, the subquery generates a new table that will be used for the rest of the query.
10 | * When using subqueries in the `SELECT` clause, the subquery produces a sub-select expression that returns a single value.
11 |
12 |
13 |
14 | ### Using a Subquery in the From Clause
15 |
16 | Lets create a query that scales all the movie ratings depending on which year they were produced. For example, a movie produced in 2012 with a rating of 4 would be higher ranked than a movie produced in 1990 with a rating of 4. Lets assume that throughout the years in the movie industry, the CGI and film effects get better, thus producing a better movie. This technology wouldn't be available in the previous years, so older movie's ratings won't hold the same value as present day movies.
17 |
18 | Our query would look like this:
19 |
20 | ```sql
21 | SELECT *
22 | FROM (SELECT M.mID, Title, Year, Rating, Rating*(Year/1000.0) as scaledRating
23 | FROM Movie M, Review
24 | WHERE M.mID = Review.mID) sR
25 | WHERE abs(sR.scaledRating) > 8;
26 | ```
27 | This query is saying that it will `SELECT` all attributes `FROM` a table produced by a subquery. This subquery is going to produced a table that has the `mID`, `Title`, `Year`, `Rating`, then a scaled rating with a column name as `scaledRating`. The results of this subquery has the table variable name of `sR`. Then in the main query, we only want to output the movies where the absolute value (`abs()`) of the `scaledRating` is greater than 8.
28 |
29 | We would then get output the following movies: *Titanic*, and *Gravity*.
30 |
31 |
32 |
33 | ### Using Subqueries in the Select Clause
34 |
35 | Lets create a query that lists all the users and pairs them with the highest rating that they have given.
36 |
37 | The query would look like so:
38 |
39 | ```sql
40 | SELECT uID, Name
41 | (SELECT DISTINCT Rating
42 | FROM User, Review
43 | WHERE User.uID = Review.uID
44 | and Rating >= ALL
45 | (SELECT Rating
46 | FROM User, Review
47 | WHERE User.uID = Review.uID)) as hRating
48 | FROM User;
49 | ```
50 |
51 | This query says that we are going to find `uID` and that user's `Name` from the `User` table, and then it runs a subquery. The subquery looks for a `Rating` inside the table `Review`. We make sure to join the `uID` from the `User` table to the `uID` in the `Review` table. We then choose the largest `Rating` among `ALL` the `Rating`s that are associated with that user. Lastly, we give the subquery result's a variable name, which takes the name of `hRating`, which stands for 'highest rating'.
52 |
53 | In other words, we would get a resutling table with each user's `uID` and `Name`. Then, it would have a column labeled `hRating` which has the highest rating that each individual user has ever done.
54 |
55 | Our query would ouput these results:
56 |
57 | | uID | Name | hRating |
58 | | --- | ---------------- | ------- |
59 | | 201 | James Dean | 4 |
60 | | 202 | Chris Anderson | 4 |
61 | | 203 | Ashley Burley | 2 |
62 | | 204 | Ralph Truman | 4 |
63 | | 205 | Gordon Maximus | 3 |
64 | | 206 | Sarah Rodgriguez | 3 |
65 | | 207 | Darrel Sherman | 5 |
66 | | 208 | Lisa Jackson | 2 |
67 |
68 |
69 |
70 | ### Important Note on Subqueries in the Select Clause
71 |
72 | When implenting a subquery in the `SELECT` clause, it is crucial that the subquery only returns exactly one value, because the result of that subquery is being used to only fill in one cell of the parent query.
73 |
--------------------------------------------------------------------------------
/subqueries_in_the_where_clause/using_operators_in_a_subquery.md:
--------------------------------------------------------------------------------
1 | # Using Operators in a Subquery
2 |
3 |
4 |
5 |
6 | ### The Exist Operator & Correlated References
7 |
8 | The `EXISTS` operator checks whether a subquery is empty or not, instead of checking whether values are in the subquery.
9 |
10 | A correlated reference is where you use a value inside a subquery, that comes from *outside* that subquery.
11 |
12 | Lets look at an example:
13 |
14 | ```sql
15 | SELECT mID, Rating
16 | FROM Review R1
17 | WHERE EXISTS (SELECT * FROM Review R2
18 | WHERE R1.Rating = R2.Rating and R1.mID <> R2.mID);
19 | ```
20 | This query will return all movies that have the same rating. First we're going to take the `mID`'s from `R1`. Then we're creating a new relation called `R2`. For each movie we're going to check if there is another `mID`, where the `Rating` in `R2` is the same as the `Rating` in `R1`. We then say that each `mID` should be different, and not equal to itself.
21 |
22 | We use a correlated reference to use an outside variable *inside* a subquery.
23 |
24 |
25 |
26 | ### Looking for a Largest Value
27 |
28 | Assume that you wanted to look for the largest value of some element. In this case, we want to find the movie that was most recently created. Thus, the movie's `Year` would be the largest.
29 |
30 | We could write a query that looks like this:
31 |
32 | ```sql
33 | SELECT Title, Year
34 | FROM Movie M1
35 | WHERE NOT EXISTS (SELECT * FROM Movie M2
36 | WHERE M1.Year < M2.Year);
37 | ```
38 |
39 | This query says that we are going to find all movies where there does **not exist** another movie whose `Year` is greater than the first movie.
40 | This would be a form of query that we could write whenever looking for the greatest value of some-sort.
41 |
42 | The resulting movie would be: *Gravity*.
43 |
44 |
45 |
46 | ### The All Operator
47 |
48 | The `ALL` keyword tells us that instead of checking whether a value is in or not in the result of a subquery, we're going to check if the value has a certain relationship with `ALL` the results of a subquery.
49 |
50 | Lets create a query that checks to see if the `Rating` of a movie is greater than or equal to `ALL` elements of the subquery which returns all the `Ratings` of each movie.
51 |
52 | It would look like this:
53 |
54 | ```sql
55 | SELECT mID, Rating
56 | FROM Review
57 | WHERE Rating >= all (SELECT Rating FROM Review);
58 | ```
59 |
60 | We would then get an output table of all the movie's with a `Rating` of 5, since there is no single movie with a greater `Rating` than every other movie.
61 |
62 | The output table would include the movies: *Gravity*, and *Titanic*.
63 |
64 |
65 |
66 | ### The Any Operator
67 |
68 | The `ANY` keyword performs very similar to the `ALL` keyword, except instead of having to satisfy a condition with `ALL` of the elements of a set, it only has to satisfy a condition with at least one element of a set.
69 |
70 | Lets create a query that finds all movies that have a `Year` that is not the smallest `Year` value. In other words, we are looking for movies whose `Year` is greater than `ANY` other movie `Year`.
71 |
72 | Our query would look like this:
73 |
74 | ```sql
75 | SELECT Title, Year
76 | FROM Movie
77 | WHERE Year > ANY (SELECT Year FROM Movie);
78 | ```
79 |
80 | In the above example query, a movie will be returned if there is some other movie whose `Year` is less than this movie. We then get a resulting table with all the movies that do not have the least `Year` value. Thus, we would get every movie except for *The Godfather*, because it has the smallest `Year` value.
81 |
82 |
83 |
84 | ### Conclusion on Operators
85 |
86 | The `ANY` and `ALL` operators are very convienient when creating queries, however, they are not vital to creating a query. We can always write a query that would normally use the `ANY` or `ALL` keywords, by using the `EXISTS` or `NOT EXISTS` operators.
87 |
--------------------------------------------------------------------------------
/the_join_family_operators/the_inner_join_operator.md:
--------------------------------------------------------------------------------
1 | # The Inner Join Operator
2 |
3 |
4 |
5 |
6 | ### Basic `INNER JOIN` Query
7 |
8 | Let's create a query that you should be familiar with, which outputs the `Title` and `Rating` of all the movies.
9 |
10 | Like so:
11 |
12 | ```sql
13 | SELECT Title, Rating
14 | FROM Movie, Review
15 | WHERE Movie.mID = Review.mID;
16 | ```
17 |
18 | In the above query, we make a join relation making sure that the movie ID is the same across the `Movie` and `Review` table.
19 |
20 | Now let's rewrite it using an `INNER JOIN`:
21 |
22 | ```sql
23 | SELECT Title, RATING
24 | FROM Movie INNER JOIN Review
25 | ON Movie.mID = Review.mID;
26 | ```
27 |
28 | This query does the `INNER JOIN`, or the combination of `Movie` and `Review`, **ON** a specific condition. So it does the cross product of the two tables, then after doing the cross product, it checks the condition and only returns the elements that satisfy the condition.
29 |
30 | We would then get a table in return with every movie in the database and its `Rating`.
31 |
32 | The `INNER JOIN` operator is the default operator in SQL, and even if you were to take out the `INNER` and just write: `
JOIN
`, it would default to an `INNER JOIN`.
33 |
34 |
35 |
36 | ### Inner Join with Multiple Conditions
37 |
38 | Let's create another query that gets the `Title` and `Rating` of all movies whose `Rating` is greater than 3, and was produced after the year 1990.
39 |
40 | Like so:
41 |
42 | ```sql
43 | SELECT Title, Rating
44 | FROM Movie, Review
45 | WHERE Movie.mID = Review.mID
46 | and Rating > 3 and Year > 1990;
47 | ```
48 |
49 | Let's now rewrite this query to use the `INNER JOIN` operator. Our query would look like this:
50 |
51 | ```sql
52 | SELECT Title, Rating
53 | FROM Movie JOIN Review
54 | ON Movie.mID = Review.mID
55 | and Rating > 3 and Year > 1990;
56 | ```
57 |
58 | Our query selects all movies whose `Rating` is greater than 3, and whose `Year` is greater than 1990. It joins the `Movie` and `Review` tables, and the join relation is again combining the `Movie` and `Review` records where the `mID` matches. It then checks the condition and returns the tuples that satisfy the condition.
59 |
60 | We would then get the following movies in return: *Gravity*, *The Lion King*, *Titanic*, and *Cast Away*.
61 |
62 | The `ON` condition can also be ran using the `WHERE` clause, but it's more efficient to use the `ON` operator for reasons I will not get into here.
63 |
64 |
65 |
66 | ### Running a Query with Three Relations
67 |
68 | We will create a query that just gets all the general information on each individual movie, and also return all the user's names.
69 |
70 | Our query will look like this:
71 |
72 | ```sql
73 | SELECT Movie.mID, Title, Year, Director, Rating, User.uID Name
74 | FROM Movie, User, Review
75 | WHERE Movie.mID = Review.mID
76 | and User.uID = Review.uID;
77 | ```
78 |
79 | Now lets rewrite it using a join operator:
80 |
81 | ```sql
82 | SELECT Movie.mID, Title, Year, Director, Rating, User.uID, Name
83 | FROM Movie JOIN User JOIN Review
84 | ON Movie.mID = Review.mID
85 | and User.uID = Review.uID;
86 | ```
87 |
88 | In this particular query, we would **possibly** get an error depending on the type of system that you are using. A few SQL sytems are: SQLite, MySQL, and Postrisk.
89 |
90 | If working in the Postrisk system, we would get an error when running the above query because Postrisk does not support multiple join operators. It requires all join operations to be binary, meaning it can only join two relations. If running on the Postrisk system, you could rewrite the query to look like this:
91 |
92 | ```sql
93 | SELECT Movie.mID, Title, Year, Director, Rating, User.uID, Name
94 | FROM (Movie JOIN Review ON Movie.mID = Review.mID) JOIN User
95 | ON User.uID = Review.uID;
96 | ```
97 |
98 | Notice in the above query we joined the two relations `Movie` and `Review` and then wrapped them in parenthesis. This allows for it to satisfy the Postrisk's requirement for all join relations to be binary. We are saying "First join the `Movie` and `Review` table, then join that result with the `User` table. Lastly, we moved the `ON` condition inside the parenthesis for that particular join operator.
99 |
--------------------------------------------------------------------------------
/html_version/gitbook/print.css:
--------------------------------------------------------------------------------
1 | .link-inherit{color:inherit}.link-inherit:hover,.link-inherit:focus{color:inherit}.hidden{display:none}.hljs-comment,.hljs-title{color:#8e908c}.hljs-variable,.hljs-attribute,.hljs-tag,.hljs-regexp,.ruby .hljs-constant,.xml .hljs-tag .hljs-title,.xml .hljs-pi,.xml .hljs-doctype,.html .hljs-doctype,.css .hljs-id,.css .hljs-class,.css .hljs-pseudo{color:#c82829}.hljs-number,.hljs-preprocessor,.hljs-pragma,.hljs-built_in,.hljs-literal,.hljs-params,.hljs-constant{color:#f5871f}.ruby .hljs-class .hljs-title,.css .hljs-rules .hljs-attribute{color:#eab700}.hljs-string,.hljs-value,.hljs-inheritance,.hljs-header,.ruby .hljs-symbol,.xml .hljs-cdata{color:#718c00}.css .hljs-hexcolor{color:#3e999f}.hljs-function,.python .hljs-decorator,.python .hljs-title,.ruby .hljs-function .hljs-title,.ruby .hljs-title .hljs-keyword,.perl .hljs-sub,.javascript .hljs-title,.coffeescript .hljs-title{color:#4271ae}.hljs-keyword,.javascript .hljs-function{color:#8959a8}.hljs{display:block;background:white;color:#4d4d4c;padding:.5em}.coffeescript .javascript,.javascript .xml,.tex .hljs-formula,.xml .javascript,.xml .vbscript,.xml .css,.xml .hljs-cdata{opacity:.5}.book-chapter{display:none}.exercise,.quiz{margin:1cm 0;padding:.4cm;page-break-inside:avoid;border:3px solid #ddd}.exercise .exercise-header,.quiz .exercise-header{margin-bottom:.4cm;padding-bottom:.2cm;border-bottom:1px solid #ddd}.exercise .question,.quiz .question{margin-top:.4cm}body{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;line-height:1.4;color:#333;overflow:hidden;line-height:1.6;word-wrap:break-word;display:block}body>*:first-child{margin-top:0!important}body>*:last-child{margin-bottom:0!important}body a{background:transparent}body a:active,body a:hover{outline:0}body strong{font-weight:bold}body h1{font-size:2em;margin:.67em 0}body img{border:0}body hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}body pre{overflow:auto}body code,body pre{font-family:monospace,monospace;font-size:1em}body table{border-collapse:collapse;border-spacing:0}body td,body th{padding:0}body *{-moz-box-sizing:border-box;box-sizing:border-box}body a{color:#4183c4;text-decoration:none}body a:hover,body a:focus,body a:active{text-decoration:underline}body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #ddd}body hr:before,body hr:after{display:table;content:" "}body hr:after{clear:both}body h1,body h2,body h3,body h4,body h5,body h6{margin-top:15px;margin-bottom:15px;line-height:1.1}body h1{font-size:30px}body h2{font-size:21px}body h3{font-size:16px}body h4{font-size:14px}body h5{font-size:12px}body h6{font-size:11px}body blockquote{margin:0}body ul,body ol{padding:0;margin-top:0;margin-bottom:0}body ol ol{list-style-type:lower-roman}body dd{margin-left:0}body code,body pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px}body pre{margin-top:0;margin-bottom:0}body .markdown-body>*:first-child{margin-top:0!important}body .markdown-body>*:last-child{margin-bottom:0!important}body .anchor{position:absolute;top:0;bottom:0;left:0;display:block;padding-right:6px;padding-left:30px;margin-left:-30px}body .anchor:focus{outline:0}body h1,body h2,body h3,body h4,body h5,body h6{position:relative;margin-top:1em;margin-bottom:16px;font-weight:bold;line-height:1.4}body h1{padding-bottom:.3em;font-size:2.25em;line-height:1.2;border-bottom:1px solid #eee}body h2{padding-bottom:.3em;font-size:1.75em;line-height:1.225;border-bottom:1px solid #eee}body h3{font-size:1.5em;line-height:1.43}body h4{font-size:1.25em}body h5{font-size:1em}body h6{font-size:1em;color:#777}body p,body blockquote,body ul,body ol,body dl,body table,body pre{margin-top:0;margin-bottom:16px}body hr{height:4px;padding:0;margin:16px 0;background-color:#e7e7e7;border:0 none}body ul,body ol{padding-left:2em}body ol ol,body ol ul{margin-top:0;margin-bottom:0}body dl{padding:0}body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:bold}body dl dd{padding:0 16px;margin-bottom:16px}body blockquote{padding:0 15px;color:#777;border-left:4px solid #ddd}body blockquote>:first-child{margin-top:0}body blockquote>:last-child{margin-bottom:0}body table{display:block;width:100%;overflow:auto}body table th{font-weight:bold}body table th,body table td{padding:6px 13px;border:1px solid #ddd}body table tr{background-color:#fff;border-top:1px solid #ccc}body table tr:nth-child(2n){background-color:#f8f8f8}body img{max-width:100%;-moz-box-sizing:border-box;box-sizing:border-box;page-break-inside:avoid}body code{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:#f7f7f7;border-radius:3px}body code:before,body code:after{letter-spacing:-0.2em;content:"\00a0"}body pre>code{padding:0;margin:0;font-size:100%;white-space:pre;background:transparent;border:0}body .highlight pre,body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f7f7f7;border:0;border-radius:3px}body pre{word-wrap:normal}body pre code{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}body pre code:before,body pre code:after{content:normal}body .highlight{background:#fff}
--------------------------------------------------------------------------------
/table_variables_&_set_operators/README.md:
--------------------------------------------------------------------------------
1 | # Table Variables & Set Operators
2 |
3 |
4 |
5 |
6 | ### What are they?
7 |
8 | Take a look at the code block below:
9 |
10 | ```sql
11 | SELECT A1, A2, . . . , A(n)
12 | FROM R1, R2, . . . , R(m)
13 | WHERE ;
14 | ```
15 |
16 | All of the variables inside the `FROM` clause are called table variables. They help with making the query more readable, and they rename relations within the `FROM` clause when we have more than one instance of a relation.
17 |
18 | The second construct is called a set operator. A few examples of them are: the `UNION` operator, the `INTERSECT` operator, and the `EXCEPT` operator.
19 |
20 |
21 |
22 | ### Adding Table Variables for Readability
23 |
24 | Let's assume we want to make a query that outputs all the movies along with their movie ID, title, User ID, User name, and rating.
25 |
26 | Our query would look like this:
27 |
28 | ```sql
29 | SELECT Movie.mID, Title, User.uID, Name, Rating
30 | FROM Movie, User, Review
31 | WHERE Movie.mID = Review.mID and User.uID = Review.uID;
32 | ```
33 |
34 | We would then get our expected table output. However, to make the query a little more readable, we can place variables inside the `FROM` clause, and replace all the table names with just the table variable.
35 |
36 | Our query would look like this:
37 |
38 | ```sql
39 | SELECT M.mID, Title, U.uID, Name, Rating
40 | FROM Movie M, User U, Review R
41 | WHERE M.mID = R.mID and U.uID = R.uID;
42 | ```
43 |
44 | Notice how we added `M` after `Movie` inside the `FROM` clause. That is called adding a table variable, then where ever we used `Movie` in our entire select statement, we can just replace with `M`. We also did the same thing for `User U` and `Review R`.
45 |
46 |
47 |
48 | ### Adding Table Variables for Multiple Instances
49 |
50 | In this next query, we want to find all movies that have the exact same rating. In order to do that, we need to have two instances of `Review`. We will call the first instance `R1` and the second instance `R2`. We also need to include `Movie` in the `FROM` clause to get the movie `Title`.
51 |
52 | Our query would look like this:
53 |
54 | ```sql
55 | SELECT DISTINCT Movie.mID, Title, R1.Rating
56 | FROM Movie M, Review R1, Review R2
57 | WHERE R1.Rating = R2.Rating and R1.mID = M.mID and R1.mID <> R2.mID and R1.uID <> R2.uID;
58 |
59 | ```
60 |
61 | We first added the two table variables: `R1` and `R2` to separate each instance. We are looking for the `mID`'s, `Title`'s, and `Rating`'s of each movie. We specify `DISTINCT` in the `WHERE` clause to remove duplicates. We then place a condition in the `WHERE` clause to specify that we want to output movies with the same rating. We include the join condition `R1.mID = M.mID` to make sure the movies are the same in each relation.
62 | We then specify two final clauses: `and R1.mID <> R2.mID and R1.uID <> R2.uID;`. `R1.mID <> R2.mID` tells the computer that the `R1.mID` is different from `R2.mID`, or that movie 1 needs to be different from movie 2. If we didn't specify this clause, we would get an output of movies that equal themselves, because movie 1 would have the same `Rating` as itself, thus satisfying the condition. Likewise, `R1.uID <> R2.uID` makes sure we don't get back two instances of a review by the same reviewer.
63 |
64 |
65 | ### The Union Operator
66 |
67 | The `UNION` operator allows us to create queries that will output a list of elements that come from multiple tables. Previously we could only separate these elements into different columns. However, by using the `UNION` operator, we can get elements from different tables listed into a single column together.
68 |
69 | For example, if we wanted to get a single list of all the movie titles and reviewer names, we would create a query that looks like this:
70 |
71 | ```sql
72 | SELECT Title FROM Movie
73 | UNION
74 | SELECT Name FROM User;
75 | ```
76 |
77 | We would then get a table with only **one** column, and it would list each movie title and each reviewer name.
78 |
79 |
80 |
81 | ### Specifying a Column Name
82 |
83 | By default, SQL would pick label the column either `Title` or `Name`. If you wanted to specify a label for the column, you would use the `AS` operator.
84 |
85 | It would look like this:
86 |
87 | ```sql
88 | SELECT Title AS list FROM Movie
89 | UNION
90 | SELECT Name AS list FROM User;
91 | ```
92 |
93 | Notice how we placed `AS list` in each select clause, and this tells SQL to name the column `list`.
94 |
95 |
96 |
97 | ### The Intersect Operator
98 |
99 | The `INTERSECT` operator takes away the necessity to specify a joint relation. It automatically knows that each select statement in the query is for the same movie.
100 |
101 | If we wanted to create a query that searched for movies that were created before the year 2000, and had a `mID` of less than 105, we could use the `INTERSECT` operator.
102 |
103 | Our query would look like this:
104 |
105 | ```sql
106 | SELECT Title FROM Movie WHERE Year < 2000
107 | INTERSECT
108 | SELECT Title FROM Movie WHERE mID < 105;
109 | ```
110 |
111 | We would then get a table in return with all the movies that were created before the year 2000, and had a `mID` less than 105.
112 |
113 | The resulting movies would be: *Top Gun*, *Titanic*, and *The Lion King*.
114 |
115 |
116 |
117 | ### The Except Operator
118 |
119 | The `EXCEPT` operator does exactly the opposite of the `INTERSECT` operator.
120 |
121 | Lets create a query that looks for movies that were created before the year 2000, but **do not** have a `mID` less than 105.
122 |
123 | Our query would look like this:
124 |
125 | ```sql
126 | SELECT Title FROM Movie WHERE Year < 2000
127 | EXCEPT
128 | SELECT Title FROM Movie WHERE mID < 105;
129 | ```
130 |
131 | In this case, the `EXCEPT` operator tells SQL to look for movies that were made before the year 2000, and then take away the movies with a `mID` less than 105. This then leaves us with a result of movies which were created before 2000, but have a `mID` greater than or equal to 105.
132 |
133 | The resulting movie would be: *The Godfather*.
134 |
--------------------------------------------------------------------------------
/aggregation/aggregation_functions.md:
--------------------------------------------------------------------------------
1 | # Aggregation Functions
2 |
3 |
4 |
5 |
6 | ### Basic Aggregation Query
7 |
8 | Our first aggregation query is going to compute the average movie `Rating` of the movies in the database.
9 |
10 | Like so:
11 |
12 | ```sql
13 | SELECT AVG(Rating)
14 | FROM Review;
15 | ```
16 |
17 | We would then get a single cell back with the result of: `3.333333333`. All the ratings add up to 40, and there are twelve ratings, so 40/12 = 3.33 repeating.
18 |
19 |
20 |
21 | ### Aggregation and Joins
22 |
23 | Our second query is going to be a little more complicated. It finds the minimum `Rating` of movies that were produced before the year `2000`.
24 |
25 | Our query would look like this:
26 |
27 | ```sql
28 | SELECT MIN(Rating)
29 | FROM Movie, Review
30 | WHERE Movie.mID = Review.mID and Year < 2000
31 | ```
32 |
33 | The above query is saying that the aggregation is going to look at the `Rating` column and it's going to find the lowest value. It is going to look inside the `Movie` and `Review` tables, it will join the `mID` across both relations, and will filter for movies that were produced before the year 2000.
34 |
35 | Our resulting movie would be *Top Gun*.
36 |
37 | Now lets go back to our `AVG` aggregation query again. We will again compute the average `Rating` of all the movies that were produced after the year 1995. However, we have to change up the query because some movies were rated more than once, and we don't want to include the duplicate ratings in our average rating computation. We only want to count the `Rating` one time for each movie. In order to do that, we need to use a subquery from where we select from `Review`, and then we just want to check for each movie whether their ID is among those whose year is greater than 1995.
38 |
39 | Our query would look like this:
40 |
41 | ```sql
42 | SELECT AVG(Rating)
43 | FROM Review
44 | WHERE mID IN (SELECT mID FROM Movie WHERE Year > 1995);
45 | ```
46 |
47 | So now we would get a resulting table where the `Rating` for each movie is only counted once in the computation. Our average `Rating` for all movies produced after the year 1995 would be: 3.
48 |
49 |
50 |
51 | ### The `COUNT` Function
52 |
53 | The `COUNT` function, not suprisingly, counts the number of tuples in the result that meet the `WHERE` condition.
54 |
55 | Like so:
56 |
57 | ```sql
58 | SELECT COUNT(*)
59 | FROM Movie
60 | WHERE Year > 1990;
61 | ```
62 |
63 | We are `SELECT`ing all attributes inside the `Movie` table, and we are going to `COUNT` the number of movies whose year is greater than 1990.
64 |
65 | Our result would be the number 6, because the following movies all were produced after the year 1990: *The Lion King*, *Titanic*, *Gravity*, *Harry Potter*, *Cast Away*, and *Spiderman*.
66 |
67 | Now lets create another query that counts the number of movies with a `Rating` greater than 3.
68 |
69 | It would look like this:
70 |
71 | ```sql
72 | SELECT COUNT(*)
73 | FROM Review
74 | WHERE Rating > 3;
75 | ```
76 |
77 | We would then get a result of 6. However, there are some movies that were rated more than once and who have multiple ratings greater than 3, so we want to eliminate the duplicates and only count each movie once.
78 |
79 | Our new query would look like this:
80 |
81 | ```sql
82 | SELECT COUNT(DISTINCT mID)
83 | FROM Review
84 | WHERE Rating > 3;
85 | ```
86 |
87 | SQL includes a nice keyword for us ot use in this particular query. In the `COUNT` function we put the `DISTINCT` keyword and then the name of the attribute that `COUNT` will look for. In this case, `COUNT` will look at the result, and then it will count the distinct values for the particular attribute.
88 |
89 | Our result would be the number 5, because the movie *Gravity* was rated twice with a `Rating` greater than 3. So now we eliminate the duplicate and get our correct result by only counting each movie once in the computation.
90 |
91 |
92 |
93 | ### Aggregation in Subqueries
94 |
95 | We're going to write up a fairly complicated query this time. This query computes the difference of the average `Rating` between movies produced after the year 2000, and movies produced before the year 2000.
96 |
97 | Our query will look like this:
98 |
99 | ```sql
100 | SELECT Post.avgRating - Pre.avgRating
101 | FROM
102 | (SELECT AVG(Rating) as avgRating
103 | FROM Review
104 | WHERE mID IN
105 | (SELECT mID FROM Movie WHERE Year >= 2000)) as Post
106 | (SELECT AVG(Rating) as avgRating
107 | FROM Review
108 | WHERE mID NOT IN
109 | (SELECT mID FROM Movie WHERE Year >= 2000)) as Pre;
110 | ```
111 |
112 | In the above query we are using subqueries in the `FROM` clause. Recall from earlier chapters that a subquery in the `FROM` clause allows you to write a select statement, and then use the result as if it were an actual relation in the database. So we are going to compute two subqueries in the `FROM` clause, one of them computing the average `Rating` of movies that were produced on or after the year 2000, and the second one computing the average `Rating` of movies that were NOT produced on or after the year 2000.
113 |
114 | So lets walk through the query:
115 | * The first subquery says, let's find the movies whose `Year` is greater than or equal to 2000, let's compute their average `Rating`, and we will call it `avgRating`. We will take the whole result of this query and then name it `Post`, as in post-2000.
116 | * Similarly the second relation that we are computing in the `FROM` clause computes the average `Rating` of movies whose `Year` is not greater than or equal to 2000, so their `mID` is `NOT IN` the set of movies whose `Year` is greater than 2000. We then name the result of this query `Pre`, as in pre-2000.
117 | * To conclude, in the `FROM` clause we now have a relation called `Post` with an attribute called `avgRating`, and a second relation called `Pre` with an attribute called `avgRating`. Then, in the `SELECT` clause of the main query, we subtract the `avgRating` of movies from `Pre` from the `avgRating` of movies from `Post`.
118 |
119 | If we were to run the query, we would get the result of: 0. Thus, that means the average `Rating` of movies produced before the year 2000 is exactly the same as the average `Rating` of movies produced on or after the year 2000.
120 |
--------------------------------------------------------------------------------
/html_version/GLOSSARY.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Glossary | My Book
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
184 |
185 |
186 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/basic_select_statements/README.md:
--------------------------------------------------------------------------------
1 | # Basic Select Statements
2 |
3 |
4 |
5 |
6 | ### The Three Clauses:
7 |
8 | The select statement has three clauses: the `FROM` clause, the `WHERE` clause, and the `SELECT` clause. The basic concept is that the `FROM` clause identifies the relation that you want to query over, the 'WHERE' condition is used to combine the relations and filter the relations, and the `SELECT` tells you what to return.
9 |
10 | The syntax looks like this:
11 |
12 | ```sql
13 | SELECT A1, A2, . . . , A(n)
14 | FROM R1, R2, . . . , R(m)
15 | WHERE ;
16 | ```
17 |
18 | Since relational query languages are compositional, when you run a query over relations, you get a relation as a result. Thus, the result of the above select statement is a relation, but it doesn’t have a name. The schema of that relation is the set of attributes that are returned.
19 |
20 |
21 |
22 | ### A Basic Query:
23 |
24 | Assume we have a database with three tables:
25 | 1. A `MOVIE` table that has four columns labeled `mID` (movie ID), `Title`, `Year`, and `Director`.
26 |
27 | 2. A `User` table that has two columns labeled `uID` (User ID), and `Name`.
28 |
29 | 3. Lastly, a `Review` table that has four columns labeled `uID`, `mID`, `Rating`, and `ratingDate`.
30 |
31 |
32 |
33 | *(This sample database can be viewed in the Introduction chapter of this book.)*
34 |
35 | ---
36 |
37 |
38 |
39 | We’re going to do a basic query that finds the `Title`, and `Year` of movies that were created after the year 2000. The `SELECT` tells us what we want to get out of the query, the `FROM` tells us our table name, and the `WHERE` gives us the filtering condition.
40 |
41 | The query would look like this:
42 |
43 | ```sql
44 | SELECT Title, Year
45 | FROM Movie
46 | WHERE Year > 2000;
47 | ```
48 |
49 | We would then get a table back that would have two columns labeled `Title`, and `Year`. It would then display all the movies that were created after the year 2000.
50 |
51 | The resulting movies would include: *Gravity*, *Harry Potter*, *Cast Away*, and *Spiderman*.
52 |
53 |
54 |
55 | ### Combing Two Relations:
56 |
57 | Now let’s create a query that combines two relations, such as finding movie titles, mID's and the rating that the movie recieved. We’re now involving the `Movie` table, and the `Review` table.
58 |
59 | Combining relations looks like this:
60 |
61 | ```sql
62 | SELECT Movie.mID, Title, Rating
63 | FROM Movie, Review
64 | WHERE Movie.mID = Review.mID;
65 | ```
66 |
67 | The condition above is called a **join** condition and is saying that we want to combine movies with review statistics that have the same `mID`. We would then get a table as a result with three columns labeled `mID`, `Title`, and `Rating`. It would then display all the movies with their `mID` and their `Rating`.
68 |
69 |
70 |
71 | ### Combing Two Relations w/ a Condition:
72 |
73 | The next query is going to find the `Title`, `mID` and `Rating` of movies that were created before the year 2000, and `Rating` is greater than 2.
74 |
75 | It would look like this:
76 |
77 | ```sql
78 | SELECT Movie.mID, Title, Rating
79 | FROM Movie, Review
80 | WHERE Movie.mID = Review.mID
81 | and Rating > 2 and Year < 2000;
82 | ```
83 |
84 | So in this case, we are looking for `mID`, `Title`, and `Rating`. We are looking inside the `Movie` and `Review` tables, and we have a join condition making sure that the query knows the `mID` in the `Movie` table is the same `mID` in the `Review` table. We are filtering the results based on the year the movie was created, and the rating it recieved. We would then get a table with the results of the query. The results would include all movies that were created before the year 2000, with a rating greater than 2.
85 |
86 | The resulting movies would be: *Top Gun*, *Titanic*, *The Lion King*, and *The Godfather*.
87 |
88 |
89 |
90 | ### Combining Three Relations:
91 |
92 | This time we are going to combine all three relations, and we’re going to get a table with the results of every `mID`, `Title`, `Year`, User `Name`, and `Rating`.
93 |
94 | It would look like this:
95 |
96 | ```sql
97 | SELECT Movie.mID, Title, Year, Name, User.uID, Rating
98 | FROM Movie, User, Review
99 | WHERE Movie.mID = Review.mID and User.uID = Review.uID;
100 | ```
101 |
102 | Notice how in the `SELECT` and `WHERE` statements, we specify which table we want to pull some of the attributes out of. Since there is more than one table with `mID` and `uID`, we need to specify which table we want to pull it out of. It doesn’t matter which table we specify, but if we don’t specify we will get an error because the computer doesn't know which table to pull from.
103 |
104 |
105 |
106 | ### Sorting Table Results:
107 |
108 | SQL by default does not order table results in any particular order. However, if we specify a specific order that we want, we can get results sorted by a specific attribute, or set of attributes. Say we want to sort all of our movies by descending `Rating`. In order to do this, we need to add an additional clause called the `ORDER BY` clause. If we want to get a descending order, we write what we want to search for and then use the keyword `DESC`.
109 |
110 | It would look like this:
111 |
112 | ```sql
113 | SELECT Movie.mID, Title, Year, Name, User.uID, Rating
114 | FROM Movie, User, Review
115 | WHERE Movie.mID = Review.mID and User.uID = Review.uID
116 | ORDER BY Rating DESC;
117 | ```
118 |
119 | If we wanted to have it sort by additional attributes, we would just put a comma after `DESC`, and add another attribute. However, SQL defaults to ascending order, so you need to specify which way you prefer for any additional attributes that you add.
120 |
121 |
122 |
123 | ### Doing Arithmetic within Select Statements:
124 |
125 | While doing a `SELECT` statement, SQL allows for doing arithmetic operations. Say we want to find all the movie's attributes, but add to it a scaled `Rating`. Where we are going to scale the rating by 10 to get ratings that are in the teens.
126 |
127 | The query would look like this:
128 |
129 | ```sql
130 | SELECT Movie.mID, Title, Rating, Director, Rating + 10
131 | FROM Movie, Review;
132 | ```
133 |
134 | We would then get a table with all of the above attributes, and then an additional column that shows the movie's `Rating` after being scaled by 10. However, we will get a column labeled `Rating + 10`, but we want to change it to a different particular label.
135 |
136 | We would just use the AS clause like so:
137 |
138 | ```sql
139 | SELECT Movie.mID, Title, Rating, Director, Rating + 10 AS ScaledRating
140 | FROM Movie, Review;
141 | ```
142 |
143 | We would then have a column labeled `ScaledRating` instead of `Rating + 10`.
144 |
--------------------------------------------------------------------------------
/html_version/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Introduction | My Book
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |