{"id":21253226,"url":"https://github.com/roger-takeshita/sql","last_synced_at":"2025-10-19T18:04:23.803Z","repository":{"id":120935420,"uuid":"295820931","full_name":"Roger-Takeshita/SQL","owner":"Roger-Takeshita","description":"SQL Cheat Sheets","archived":false,"fork":false,"pushed_at":"2022-05-06T03:52:43.000Z","size":28913,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-21T21:11:19.704Z","etag":null,"topics":["postgres","postgresql","sql"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Roger-Takeshita.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-15T18:50:33.000Z","updated_at":"2022-01-06T01:39:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"6a089826-3d4d-4a24-aecb-e123b29ec5e4","html_url":"https://github.com/Roger-Takeshita/SQL","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Roger-Takeshita%2FSQL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Roger-Takeshita%2FSQL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Roger-Takeshita%2FSQL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Roger-Takeshita%2FSQL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Roger-Takeshita","download_url":"https://codeload.github.com/Roger-Takeshita/SQL/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243690142,"owners_count":20331727,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["postgres","postgresql","sql"],"created_at":"2024-11-21T03:50:51.758Z","updated_at":"2025-10-19T18:04:18.750Z","avatar_url":"https://github.com/Roger-Takeshita.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 id='summary'\u003eSummary\u003c/h1\u003e\n\n- [RELATIONAL DATABASE AND SQL](#relational-database-and-sql)\n  - [Anatomy of a Relational Database](#anatomy-of-a-relational-database)\n    - [Tables](#tables)\n    - [Columns](#columns)\n  - [Creating Database and a Table](#creating-database-and-a-table)\n  - [Creating a Table for a Related Data Entry](#creating-a-table-for-a-related-data-entry)\n- [PostgreSQL Commands](#postgresql-commands)\n  - [Terminal](#terminal)\n  - [Managing Databases](#managing-databases)\n    - [Create a Database](#create-a-database)\n    - [Delete a Database](#delete-a-database)\n  - [Managing Tables](#managing-tables)\n    - [Add a New Column to a Table](#add-a-new-column-to-a-table)\n    - [Delete a Column from a Table](#delete-a-column-from-a-table)\n    - [Rename a Column](#rename-a-column)\n    - [Rename a Table](#rename-a-table)\n  - [Managing Indexes](#managing-indexes)\n    - [Removing a Specified Index from a Table](#removing-a-specified-index-from-a-table)\n  - [Querying Data from Tables](#querying-data-from-tables)\n    - [Query All Data from a Table](#query-all-data-from-a-table)\n    - [Query Data from Specified Columns](#query-data-from-specified-columns)\n    - [Query Data Using a Filter - WHERE Operator](#query-data-using-a-filter---where-operator)\n    - [Query Data - LIKE Operator](#query-data---like-operator)\n    - [Query Data - IN Operator](#query-data---in-operator)\n    - [Query Data - Constrain the Returned Rows - LIMIT Operator](#query-data---constrain-the-returned-rows---limit-operator)\n    - [Query Data - JOIN](#query-data---join)\n    - [Return the Number of Rows of a Table](#return-the-number-of-rows-of-a-table)\n    - [Sort Rows in Ascending or Descending Order - ORDER BY](#sort-rows-in-ascending-or-descending-order---order-by)\n    - [Filter Groups - HAVING Clause](#filter-groups---having-clause)\n  - [Set Operations](#set-operations)\n    - [Combine the Result - Two or More Queries - UNION Operator](#combine-the-result---two-or-more-queries---union-operator)\n    - [Minus a Result - EXCEPT Operator](#minus-a-result---except-operator)\n    - [Get Intersection of the Result Sets of Two Queries](#get-intersection-of-the-result-sets-of-two-queries)\n  - [Modifying Data](#modifying-data)\n    - [Insert a New Row Into a Table](#insert-a-new-row-into-a-table)\n    - [Insert Multiple Rows Into a Table](#insert-multiple-rows-into-a-table)\n    - [Update Data for All Rows](#update-data-for-all-rows)\n    - [Update Data from a Set of Rows Specified by a Condition - WHERE clause](#update-data-from-a-set-of-rows-specified-by-a-condition---where-clause)\n    - [Delete All Rows of a Table](#delete-all-rows-of-a-table)\n    - [Delete a Specific Row Based on a Condition](#delete-a-specific-row-based-on-a-condition)\n- [ADVANCED](#advanced)\n  - [Aliases](#aliases)\n  - [Extract](#extract)\n  - [Having](#having)\n  - [Concatenate Results](#concatenate-results)\n  - [SUM](#sum)\n  - [LIKE vs. ILIKE](#like-vs-ilike)\n  - [Case Statements](#case-statements)\n  - [Union](#union)\n  - [Coalesce](#coalesce)\n  - [Window Functions](#window-functions)\n    - [Cumulative Sales](#cumulative-sales)\n    - [Percentiles](#percentiles)\n    - [Group Level Results](#group-level-results)\n    - [Subqueries](#subqueries)\n    - [Views](#views)\n    - [Temporary Tables](#temporary-tables)\n- [EXERCISES](#exercises)\n  - [Exercise 1](#exercise-1)\n  - [Exercise 2](#exercise-2)\n  - [Exercise 3](#exercise-3)\n  - [Exercise 4](#exercise-4)\n\n# RELATIONAL DATABASE AND SQL\n\n## Anatomy of a Relational Database\n\n[Go Back to Summary](#summary)\n\n- The structure of a a particular database is known as its **schema**.\n- Schemas include the definition of such things as the database's:\n  - Tables, including the number and data type of each column\n  - Indexes for efficient access of data.\n  - Constrains (rules, such as whether a field can e null or not)\n\n### Tables\n\n[Go Back to Summary](#summary)\n\n- Database tables look like a spreadsheet since they consist of columns and rows.\n- Tables are also known as **relations**.\n- A single table in a relational database holds data for a particular data entry.\n- Since only one type of data can be held in a single table, related data, we will have different tables storing different contents and tye are **linked** via what is known as a **foreign key (FK)**.\n\n- **Foreign key** fields hold the value of its parent's **primary key (PK)**.\n- The naming convention is typically snake_cased and always plural.\n\n### Columns\n\n[Go Back to Summary](#summary)\n\n- The columns of a table have a:\n  - Name\n  - Data type\n  - Optional contrains\n- The typical naming convention is usually snake_cased and singular.\n\n- PostgreSQL has [many data types](https://www.postgresql.org/docs/11/datatype.html) for columns, but common ones include:\n\n  - Integer\n  - Decimal\n  - Varchar (variable-length strings)\n  - Text (unlimited length strings)\n  - Date (**does not** include time)\n  - Timestamps (both date and time)\n  - Boolean\n\n- Common constrains for a column include:\n  - `PRIMARY KEY`: column, or group of columns, uniquely identify a row.\n  - `REFERENCES` (Foreign Key): value in column must match the primary key in another table.\n  - `NOT NULL`: column must have a value, it cannot be empty (null).\n  - `UNIQUE`: data in this column must be unique among all rous in the table.\n\n## Creating Database and a Table\n\n[Go Back to Summary](#summary)\n\n- On terminal:\n\n  ```Bash\n     CREATE DATABASE music;\n\n     CREATE TABLE bands (\n        id serial PRIMARY KEY,  # serial is auto-incrementing integer\n        name varchar NOT NULL,\n        genre varchar\n     );\n  ```\n\n## Creating a Table for a Related Data Entry\n\n[Go Back to Summary](#summary)\n\n- Let's say we have the following data relationship: `Band ----\u003c Musician`\n  - A Band has many Musicians and a Musician belongs to a Band\n- Whenever you have a `one:many` relationship, the rows in the table for the many-side must include a column that references which row in the table on the on-side it belongs to.\n- This column is known as a **foreign key (FK)**\n- The FK must be the same data type is the primary key in the parent table (usually an integer).\n\n  ```Bash\n     CREATE TABLE musicians (\n        id serial PRIMARY KEY,\n        name varchar NOT NULL,\n        quote text,\n        band_id integer NOT NULL REFERENCES bands (id)\n     );\n  ```\n\n# PostgreSQL Commands\n\n## Terminal\n\n[Go Back to Summary](#summary)\n\n- Run PostgreSQL on Terminal:\n\n  ```Bash\n     pqsl\n  ```\n\n- Connect to a specific database:\n\n  ```Bash\n     \\c \u003cdatabase_name\u003e\n  ```\n\n- To quit the psql\n\n  ```Bash\n     \\q\n  ```\n\n- To List all databases in the PostgreSQL database server\n\n  ```Bash\n     \\l\n  ```\n\n- To list all tables inside the databa_base that you are currentt using.\n\n  ```Bash\n     \\d\n  ```\n\n## Managing Databases\n\n[Go Back to Summary](#summary)\n\n### Create a Database\n\n```Bash\n   CREATE DATABASE \u003cdatabase_name\u003e;\n```\n\n### Delete a Database\n\n```Bash\n   DROP DATABASE \u003cdatabase_name\u003e;\n```\n\n## Managing Tables\n\n[Go Back to Summary](#summary)\n\n### Add a New Column to a Table\n\n```Bash\n   ALTER TABLE \u003ctable_name\u003e ADD COLUMN \u003ccolumn_name\u003e \u003cDATA_TYPE\u003e;\n```\n\n### Delete a Column from a Table\n\n```Bash\n   ALTER TABLE \u003ctable_name\u003e DROP COLUMN \u003ccolumn_name\u003e;\n```\n\n### Rename a Column\n\n```Bash\n   ALTER TABLE \u003ctable_name\u003e RENAME \u003ccolumn_name\u003e TO \u003cnew_column_name\u003e;\n```\n\n### Rename a Table\n\n```Bash\n   ALTER TABLE \u003ctable_name\u003e RENAME TO \u003cnew_table_name\u003e;\n```\n\n## Managing Indexes\n\n[Go Back to Summary](#summary)\n\n### Removing a Specified Index from a Table\n\n```Bash\n   DROP INDEX \u003cindex_name\u003e;\n```\n\n## Querying Data from Tables\n\n[Go Back to Summary](#summary)\n\n### Query All Data from a Table\n\n```Bash\n   SELECT * FROM \u003ctable_name\u003e;\n```\n\n### Query Data from Specified Columns\n\n```Bash\n   SELECT \u003ccolumn_name_1\u003e, \u003ccolumn_name_2\u003e, ... FROM \u003ctable_name\u003e;\n```\n\n### Query Data Using a Filter - WHERE Operator\n\n```Bash\n   SELECT * FROM \u003ctable_name\u003e WHERE \u003ccondition\u003e;\n```\n\n### Query Data - LIKE Operator\n\n```Bash\n   SELECT * FROM \u003ctable_name\u003e WHERE \u003ccolumn_name\u003e LIKE '%value%';\n```\n\n### Query Data - IN Operator\n\n```Bash\n   SELECT * FROM \u003ctable_name\u003e WHERE \u003ccolumn_name\u003e IN (value_1, value2, ...);\n```\n\n### Query Data - Constrain the Returned Rows - LIMIT Operator\n\n```Bash\n   SELECT * FROM \u003ctable_name\u003e LIMIT \u003climit\u003e OFFSET \u003coffset\u003e ORDER BY \u003ccolumn_name\u003e;\n```\n\n### Query Data - JOIN\n\n- INNER JOIN, LEFT JOIN, FULL OUTER JOIN, CROSS JOIN and NATURAL JOIN\n\n  ```Bash\n    SELECT * FROM \u003ctable_name_1\u003e INNER JOIN \u003ctable_name_2\u003e ON \u003cconditions\u003e;\n  ```\n\n  ```Bash\n    SELECT * FROM \u003ctable_name_1\u003e LEFT JOIN \u003ctable_name_2\u003e ON \u003cconditions\u003e;\n  ```\n\n  ```Bash\n    SELECT * FROM \u003ctable_name_1\u003e FULL OUTER JOIN \u003ctable_name_2\u003e ON \u003cconditions\u003e;\n  ```\n\n  ```Bash\n    SELECT * FROM \u003ctable_name_1\u003e CROSS JOIN \u003ctable_name_2\u003e ON \u003cconditions\u003e;\n  ```\n\n  ```Bash\n    SELECT * FROM \u003ctable_name_1\u003e NATURAL JOIN \u003ctable_name_2\u003e ON \u003cconditions\u003e;\n  ```\n\n### Return the Number of Rows of a Table\n\n```Bash\n   SELECT COUNT (*) FROM \u003ctable_name\u003e;\n```\n\n### Sort Rows in Ascending or Descending Order - ORDER BY\n\n```Bash\n   SELECT * FROM \u003ctable_name\u003e ORDER BY \u003ccolumn_name_1\u003e, \u003ccolumn_name_2\u003e, ...;\n```\n\n### Filter Groups - HAVING Clause\n\n```Bash\n   SELECT * FROM \u003ctable_name\u003e GROUP BY \u003ccolumn_name\u003e HAVING \u003ccondition\u003e;\n```\n\n## Set Operations\n\n[Go Back to Summary](#summary)\n\n### Combine the Result - Two or More Queries - UNION Operator\n\n```Bash\n   SELECT * FROM \u003ctable_name_1\u003e UNION SELECT * FROM \u003ctable_name_2\u003e;\n```\n\n### Minus a Result - EXCEPT Operator\n\n```Bash\n   SELECT * FROM \u003ctable_name_1\u003e EXCEPT SELECT * FROM \u003ctable_name_2\u003e;\n```\n\n### Get Intersection of the Result Sets of Two Queries\n\n```Bash\n   SELECT * FROM \u003ctable_name_1\u003e INTERSECT SELECT * FROM \u003ctabble_name_2\u003e;\n```\n\n## Modifying Data\n\n[Go Back to Summary](#summary)\n\n### Insert a New Row Into a Table\n\n```Bash\n   INSERT INTO \u003ctable_name\u003e (\u003ccolumn_name_1\u003e, \u003ccolumn_name_2, ...) VALUES (\u003cvalue_1\u003e, \u003cvalue_2\u003e, ...);\n```\n\n### Insert Multiple Rows Into a Table\n\n```Bash\n   INSERT INTO \u003ctable_name\u003e (\u003ccolumn_name_1\u003e, \u003ccolumn_name_2\u003e, ...) VALUES (\u003cvalue_1\u003e, \u003cvalue_2\u003e, ...), (\u003cvalue_1\u003e, \u003cvalue_2\u003e, ...), (\u003cvalue_1\u003e, \u003cvalue_2\u003e, ...) ...;\n```\n\n### Update Data for All Rows\n\n```Bash\n   UPDATE \u003ctable_name\u003e SET \u003ccolumn_name_1\u003e = \u003cvalue_1\u003e, ...;\n```\n\n### Update Data from a Set of Rows Specified by a Condition - WHERE clause\n\n```Bash\n   UPDATE \u003ctable_name\u003e SET \u003ccolumn_name_1\u003e = \u003cvalue_1\u003e, ... WHERE \u003cconditions\u003e;\n```\n\n### Delete All Rows of a Table\n\n```Bash\n   DELETE FROM \u003ctable_name\u003e;\n```\n\n### Delete a Specific Row Based on a Condition\n\n```Bash\n   DELETE FROM \u003ctable_name\u003e WHERE \u003ccondition\u003e;\n```\n\n# ADVANCED\n\n[Go Back to Summary](#summary)\n\n- **SELECT**: choose the fields for query\n- **FROM**: pick table(s) fro data source\n- **WHERE**: filter data based upon conditions\n- **GROUP BY**: segment data into groups\n- **ORDER BY**: sort results\n- **LIMIT**: limit the number of records returned\n- **JOIN Types**:\n  - INNER vs. OUTER\n  - LEFT vs. RIGHT\n\n## Aliases\n\n[Go Back to Summary](#summary)\n\n- Rename fields in your queries:\n\n  ```SQL\n    SELECT \u003cfield\u003e AS \u003calias\u003e\n  ```\n\n  ```SQL\n    SELECT milliseconds/1000. AS seconds\n  ```\n\n- Reference tables as abbreviations:\n\n  ```SQL\n    FROM \u003ctable\u003e \u003calias\u003e\n  ```\n\n  ```SQL\n    FROM track t\n    JOIN genre g ON t.genreid = g.genreid;\n  ```\n\n  ```SQL\n    SELECT g.name,\n           AVG(t.milliseconds) / 1000. / 60. AS minutes\n    FROM track t\n      JOIN mediatype m ON t.mediatypeid = m.mediatypeid\n      JOIN genre g ON t.genreid = g.genreid\n    WHERE m.name LIKE '%audio%'\n    GROUP BY g.name\n    ORDER BY minutes DESC;\n  ```\n\n- Reference fields by position:\n\n  ```SQL\n    SELECT \u003cfield1\u003e, \u003cfield2\u003e\n    FROM \u003ctable\u003e\n    ORDER BY 1, 2\n  ```\n\n  ```SQL\n    SELECT name, milliseconds\n    FROM track\n    ORDER BY 2 DESC\n  ```\n\n  ```SQL\n    SELECT g.name,\n           AVG(t.milliseconds) / 1000. / 60. AS minutes\n    FROM track t\n      JOIN mediatype m ON t.mediatypeid = m.mediatypeid\n      JOIN genre g ON t.genreid = g.genreid\n    WHERE m.name LIKE '%audio%'\n    GROUP BY g.name\n    ORDER BY 2 DESC;\n  ```\n\n## Extract\n\n[Go Back to Summary](#summary)\n\n```SQL\n  SELECT EXTRACT ( \u003cdate_component\u003e FROM \u003cfield\u003e )\n```\n\n```SQL\n  SELECT EXTRACT ( month FROM invoicedate ) AS month\n  FROM invoice;\n```\n\n- Date/Time components\n  - Day, Month, Year\n  - Week, Month\n  - Hour, Minute, Second\n  - DOW, DOY, Quarter, Timezone\n\n## Having\n\n[Go Back to Summary](#summary)\n\n```SQL\n  SELECT \u003cfield1\u003e, \u003cagg function\u003e(\u003cfield2\u003e)\n  FROM \u003ctable\u003e\n  GROUP BY \u003cfield1\u003e\n  HAVING \u003cagg function\u003e(\u003cfield2\u003e) \u003coperator\u003e \u003cvalue\u003e;\n```\n\n```SQL\n  SELECT genreid, COUNT(trackid)\n  FROM track\n  GROUP BY genreid\n  HAVING COUNT(*) \u003e 50\n  ORDER BY genreid ASC;\n```\n\n| genreid | count |\n| ------- | ----- |\n| 1       | 1297  |\n| 2       | 130   |\n| 3       | 374   |\n| 4       | 332   |\n\n```SQL\n  SELECT genre.name,\n         AVG(track.milliseconds) / 1000. / 60. AS minutes\n  FROM track\n    JOIN mediatype ON track.mediatypeid = mediatype.mediatypeid\n    JOIN genre ON track.genreid = genre.genreid\n  WHERE mediatype.name LIKE '%audio%'\n  GROUP BY genre.name\n  HAVING AVG(track.milliseconds) / 1000. / 60. \u003e= 3\n  ORDER BY minutes DESC;\n```\n\n## Concatenate Results\n\n- Just like **\u0026** in Excel, we can use `||` to concatenate results in SQL\n\n  ```SQL\n    SELECT e.firstname || ' ' || e.lastname AS \"Employee Name\",\n           boss.firstname || ' ' || boss.lastname AS \"Boss\"\n    FROM employee e\n    FULL JOIN employee boss ON e.reportsto = boss.employeeid;\n  ```\n\n## SUM\n\n[Go Back to Summary](#summary)\n\n```SQL\n  SELECT SUM(milliseconds) / 1000. / 60. / 60. / 24. AS days\n  FROM track;\n  --  15.958079\n```\n\n## LIKE vs. ILIKE\n\n[Go Back to Summary](#summary)\n\n- `ILIKE` = case insensitive\n\n  ```SQL\n    SELECT g.name,\n          AVG(t.milliseconds) / 1000. / 60. AS minutes\n    FROM track t\n      JOIN mediatype m ON t.mediatypeid = m.mediatypeid\n      JOIN genre g ON t.genreid = g.genreid\n    WHERE m.name LIKE '%audio%'\n    GROUP BY g.name\n    ORDER BY 2 DESC;\n  ```\n\n- `LIKE` = case sensitive\n\n  ```SQL\n    SELECT genre.name,\n          AVG(track.milliseconds) / 1000. / 60. AS minutes\n    FROM track\n      JOIN mediatype ON track.mediatypeid = mediatype.mediatypeid\n      JOIN genre ON track.genreid = genre.genreid\n    WHERE mediatype.name LIKE '%audio%'\n    GROUP BY genre.name\n    HAVING AVG(track.milliseconds) / 1000. / 60. \u003e= 3\n    ORDER BY minutes DESC;\n  ```\n\n## Case Statements\n\n[Go Back to Summary](#summary)\n\n- Just like a `switch/case` in JavaScript\n\n  ```SQL\n    SELECT CASE\n      WHEN \u003c condition_1 \u003e THEN \u003c result_1 \u003e\n      WHEN \u003c condition_2 \u003e THEN \u003c result_2 \u003e\n      ELSE \u003cresult_3 \u003e\n    END;\n  ```\n\n  ```SQL\n    SELECT CASE\n      WHEN AGE \u003c 18 THEN 'child'\n      WHEN AGE \u003e= 60 THEN 'senior'\n      ELSE 'adult'\n    END AS age_market_segment;\n  ```\n\n## Union\n\n[Go Back to Summary](#summary)\n\n- Merges data from two queries by stacking results on top of each other\n- Must have same number of columns and corresponding data types\n- Duplicate results are removed by default\n- `UNION ALL` will **include duplicates**\n\n  ```SQL\n    SELECT *\n    FROM\u003c table1 \u003e\n    UNION\n    SELECT *\n    FROM\u003c table2 \u003e;\n  ```\n\n## Coalesce\n\n[Go Back to Summary](#summary)\n\n- Picks first non-null value\n\n  ```SQL\n    COALESCE ([field1], [field2], [field3])\n  ```\n\n  ```SQL\n    COALESCE(online.firstname, catalog.firstname) AS firstname\n  ```\n\n## Window Functions\n\n[Go Back to Summary](#summary)\n\n- **ATTENTION:** Not all SQL supports window function\n- Perform calculation across a set of table rows that are somehow related to the current row + all the previous\n- Applications:\n  - Cumulative sales\n  - Percentile rank\n  - Group level results\n\n### Cumulative Sales\n\n[Go Back to Summary](#summary)\n\n```SQL\n  SELECT SUM(\u003c field1 \u003e) OVER (ORDER BY\u003c field2 \u003e)\n  FROM\u003c TABLE\u003e;\n```\n\n- Example, In this case the SUM is calculated dynamically\n\n  ```SQL\n    SELECT invoicedate,\n          SUM(total) OVER (ORDER BY invoicedate)\n    FROM invoice;\n  ```\n\n### Percentiles\n\n[Go Back to Summary](#summary)\n\n```SQL\n  SELECT NTILE(\u003c # OF groups \u003e) OVER (ORDER BY\u003c field \u003e)\n  FROM\u003c TABLE\u003e;\n```\n\n```SQL\n  SELECT name,\n         milliseconds,\n         NTILE(100) OVER (ORDER BY milliseconds DESC) AS percentile\n  FROM track;\n```\n\n### Group Level Results\n\n[Go Back to Summary](#summary)\n\n```SQL\n  SELECT AVG(\u003c field1 \u003e) OVER (PARTITION BY\u003c field2 \u003e)\n  FROM\u003c TABLE\u003e;\n```\n\n```SQL\n  SELECT name,\n         genreid,\n         milliseconds,\n         AVG(milliseconds) OVER (PARTITION BY genreid)\n  FROM track;\n```\n\n### Subqueries\n\n[Go Back to Summary](#summary)\n\n```SQL\n  WITH \u003c subquery_name \u003e AS (\n      \u003c code_for_subquery \u003e\n  )\n  \u003c code_for_parent_query \u003e;\n```\n\n```SQL\n  WITH top_customers AS (\n    SELECT customerid,\n         SUM(total) AS sales\n    FROM invoice\n    GROUP BY customerid\n  )\n  SELECT COUNT(*)\n  FROM top_customers\n  WHERE sales \u003e 40;\n```\n\n### Views\n\n[Go Back to Summary](#summary)\n\n- When we create a view, this \"table\" will be permanently saved on the database. This way, anyone that has access to this table, will have access to this view\n- **ATTENTION:** You can't have duplicate field names in a view\n- **IMPORTANT:** This table is populated with new data\n\n  ```SQL\n    CREATE VIEW \u003cview_name \u003e AS \u003cquery_code \u003e; COMMIT;\n  ```\n\n  ```SQL\n    CREATE VIEW top_customers AS\n        SELECT customerid,\n              SUM(total) AS sales\n        FROM invoice\n        GROUP BY customerid\n        ORDER BY sales DESC;\n  ```\n\n### Temporary Tables\n\n[Go Back to Summary](#summary)\n\n- This will permanently create a copy of my data, but it's **deleted after you logged out**\n- **ATTENTION:** You can't have duplicate field names in a view\n- **IMPORTANT:** This table is not populated with new data that is coming in, only if we updated the temporary table\n\n  ```SQL\n    CREATE TEMP TABLE \u003c view_name \u003e AS \u003c query_code \u003e;\n  ```\n\n  ```SQL\n    CREATE TEMP TABLE total_sales AS\n        SELECT customerid,\n              SUM(total) AS sales\n        FROM invoice\n        GROUP BY customerid\n        ORDER BY sales DESC;\n  ```\n\n# EXERCISES\n\n[Go Back to Summary](#summary)\n\n## Exercise 1\n\n[Go Back to Summary](#summary)\n\n- How many days of content are there in the library?\n\n  ```SQL\n    SELECT SUM(milliseconds) / 1000. / 60. / 60. / 24. AS days\n    FROM track;\n    --  15.958079\n  ```\n\n- What are the longest songs (excluding video)?\n\n  ```SQL\n    SELECT track.name,\n          track.milliseconds / 1000. / 60. AS minutes,\n          mediatype.name\n    FROM track\n      JOIN mediatype ON track.mediatypeid = mediatype.mediatypeid\n    WHERE mediatype.name ILIKE '%AUDIO%'\n    ORDER BY track.milliseconds DESC LIMIT 100;\n  ```\n\n- What is the average length of a song grouped by genre (convert time to minutes)?\n\n  ```SQL\n    SELECT genre.name,\n           AVG(track.milliseconds) / 1000. / 60. AS minutes\n    FROM track\n      JOIN mediatype ON track.mediatypeid = mediatype.mediatypeid\n      JOIN genre ON track.genreid = genre.genreid\n    WHERE mediatype.name LIKE '%audio%'\n    GROUP BY genre.name\n    ORDER BY minutes DESC;\n  ```\n\n## Exercise 2\n\n[Go Back to Summary](#summary)\n\n- Which customers have spent more than \\$40 (Use Group By and Having for the customer and invoice tables)?\n\n  ```SQL\n    SELECT customer.firstname,\n          customer.lastname,\n          invoice.customerid,\n          SUM(invoice.total)\n    FROM customer\n      JOIN invoice ON invoice.customerid = customer.customerid\n    GROUP BY customer.firstname,\n            customer.lastname,\n            invoice.customerid\n    HAVING SUM(invoice.total) \u003e 40;\n  ```\n\n- What are the total sales by month (Use Extract and Group By and the invoice table)?\n\n  ```SQL\n    SELECT EXTRACT(month FROM invoicedate) AS month,\n          SUM(invoice.total) AS total\n    FROM invoice\n    GROUP BY month\n    ORDER BY total DESC;\n\n    SELECT EXTRACT(month FROM invoicedate) AS month,\n          SUM(invoice.total)\n    FROM invoice\n    GROUP BY month\n    ORDER BY SUM(invoice.total) DESC;\n  ```\n\n- Create a roster of employees with their bosses (Join the employee table to itself by using table aliases)\n\n  ```SQL\n    SELECT t1.firstname,\n          t1.lastname,\n          t2.firstname,\n          t2.lastname\n    FROM employee t1\n      LEFT JOIN employee t2 ON t1.reportsto = t2.employeeid;\n  ```\n\n  - Different solution\n\n  ```SQL\n    SELECT e.firstname || ' ' || e.lastname AS \"Employee Name\",\n          boss.firstname || ' ' || boss.lastname AS \"Boss\"\n    FROM employee e\n      FULL JOIN employee boss ON e.reportsto = boss.employeeid;\n  ```\n\n## Exercise 3\n\n[Go Back to Summary](#summary)\n\n- Using the iowa liquor products table, create an alcohol type label for whisky, vodka, tequila, rum, brandy, schnapps and any other liquor types (hint: use `CASE STATEMENT` and `LIKE`)\n\n  ```SQL\n    SELECT DISTINCT category_name,\n          CASE\n            WHEN category_name ILIKE '%schnapps%' THEN 'schnapps'\n            WHEN category_name ILIKE '%wisk%' OR category_name ILIKE '%scotch%' THEN 'whiskey'\n            WHEN category_name ILIKE '%vodka%' THEN 'vodka'\n            WHEN category_name ILIKE '%rum%' THEN 'rum'\n            WHEN category_name ILIKE '%brand%' THEN 'brandy'\n            WHEN category_name ILIKE '%gin%' THEN 'gin'\n            ELSE 'Other'\n          END AS liquor_type\n    FROM iowa_products\n    ORDER BY liquor_type;\n  ```\n\n- Adding a counter\n\n  ```SQL\n    SELECT category_name,\n          CASE\n            WHEN category_name ILIKE '%schnapps%' THEN 'schnapps'\n            WHEN category_name ILIKE '%wisk%' OR category_name ILIKE '%scotch%' THEN 'whiskey'\n            WHEN category_name ILIKE '%vodka%' THEN 'vodka'\n            WHEN category_name ILIKE '%rum%' THEN 'rum'\n            WHEN category_name ILIKE '%brand%' THEN 'brandy'\n            WHEN category_name ILIKE '%gin%' THEN 'gin'\n            ELSE 'Other'\n          END AS liquor_type,\n          COUNT(*)\n    FROM iowa_products\n    GROUP BY liquor_type,\n            category_name\n    ORDER BY liquor_type,\n            category_name;\n  ```\n\n- Using the catalog and online tables, create a customer list that combines the names from the catalog and online tables using UNION without creating duplicates.\n\n```SQL\n  SELECT customerid,\n         firstname AS \"First Name\",\n         lastname AS \"Last Name\"\n  FROM catalog\n  UNION\n  SELECT customerid,\n         firstname,\n         lastname\n  FROM online\n  ORDER BY \"First Name\",\n           \"Last Name\";\n```\n\n- `FULL JOIN` the catalog and online tables and inspect the results. Try adding the catalog sales and online sales totals together. Why do you get errors?\n- Wrong answer:\n\n  ```SQL\n    SELECT *,\n          c.catalogpurchases + o.onlinepurchases\n    FROM catalog c\n      FULL JOIN online o ON c.customerid = o.customerid;\n  ```\n\n- Right answer\n\n  ```SQL\n    SELECT *,\n          COALESCE(c.catalogpurchases + o.onlinepurchases) AS firstname,\n          COALESCE(c.lastname,o.lastname) AS lastname,\n          COALESCE(c.catalogpurchases,0) +COALESCE(o.onlinepurchases,0) AS total_sales\n    FROM catalog c\n      FULL JOIN online o ON c.customerid = o.customerid;\n  ```\n\n## Exercise 4\n\n[Go Back to Summary](#summary)\n\n- How many iowa liquor vendors have more than \\$1 million in 2014 sales (hint: use subquery to group sales by vendor)?\n\n```SQL\n  WITH vendor_sales AS (\n      SELECT vendor,\n          vendor_no,\n          SUM(total)\n      FROM iowa_sales\n      WHERE EXTRACT(year FROM DATE) = 2014\n      GROUP BY vendor,\n              vendor_no\n      HAVING SUM(total) \u003e 1000000\n  )\n  SELECT COUNT(*) FROM vendor_sales;\n```\n\n- Group sales by month with a subquery and then calculate cumulative sales by month for 2014 (using iowa sales table)\n\n  ```SQL\n    WITH sale_by_month AS (\n        SELECT EXTRACT(YEAR FROM iowa_sales.date) AS YEAR,\n              EXTRACT(MONTH FROM iowa_sales.date) AS MONTH,\n              SUM(total) AS new_total\n        FROM iowa_sales\n        GROUP BY YEAR,\n                MONTH\n    )\n    SELECT SUM(new_total) OVER (ORDER BY month)\n    FROM sale_by_month\n    WHERE year = 2014;\n  ```\n\n- Alternative\n\n  ```SQL\n    WITH monthly_sales AS (\n        SELECT EXTRACT(month FROM DATE) AS month,\n            SUM(total) AS sales\n        FROM iowa_sales\n        WHERE EXTRACT(year FROM DATE) = 2014\n        GROUP BY month\n    )\n    SELECT month,\n          sales / 1000000. AS month_sales,\n          TO_CHAR(sales,'999,999,999'),\n          SUM(sales) OVER (ORDER BY month) / 1000000. AS cum_sales\n    FROM monthly_sales\n    ORDER BY month;\n  ```\n\n- Alternative with monthly sales\n\n  ```SQL\n    WITH monthly_sales AS (\n        SELECT EXTRACT(month FROM DATE) AS month,\n              EXTRACT(year FROM DATE) AS year,\n              SUM(total) AS sales\n        FROM iowa_sales\n        GROUP BY month,\n                year\n    )\n    SELECT month,\n          year,\n          sales / 1000000. AS month_sales,\n          SUM(sales) OVER (PARTITION BY year ORDER BY month) / 1000000. AS cum_sales\n    FROM monthly_sales\n    ORDER BY year,\n            month;\n  ```\n\n- Create a View that adds liquor type to the iowa product data. Don't forget to commit your changes.\n\n  ```SQL\n    IF EXISTS DROP TABLE new_iowa_products;\n\n    CREATE VIEW new_iowa_products AS (\n        SELECT CASE\n            WHEN i.category_name ILIKE '%whisky%' THEN 'whisky'\n            WHEN i.category_name ILIKE '%vodka%' THEN 'vodka'\n            WHEN i.category_name ILIKE '%tequila%' THEN 'tequila'\n            WHEN i.category_name ILIKE '%rum%' THEN 'rum'\n            WHEN i.category_name ILIKE '%brandy%' THEN 'brandy'\n            WHEN i.category_name ILIKE '%schnapps%' THEN 'schnapps' ELSE 'other'\n          END AS liquor_type,\n        * FROM iowa_products AS i\n    );\n\n    COMMIT;\n\n    SELECT *\n    FROM new_iowa_products;\n  ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froger-takeshita%2Fsql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froger-takeshita%2Fsql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froger-takeshita%2Fsql/lists"}