{"id":21096510,"url":"https://github.com/terieyenike/sql-notes","last_synced_at":"2025-08-23T19:36:12.806Z","repository":{"id":197618272,"uuid":"696822589","full_name":"Terieyenike/SQL-notes","owner":"Terieyenike","description":"SQL notes - setup, creating databases, and many more","archived":false,"fork":false,"pushed_at":"2025-01-31T17:43:25.000Z","size":3477,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-01T13:07:09.933Z","etag":null,"topics":["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/Terieyenike.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,"zenodo":null}},"created_at":"2023-09-26T13:52:16.000Z","updated_at":"2025-01-31T17:43:29.000Z","dependencies_parsed_at":"2023-12-08T11:25:14.934Z","dependency_job_id":"480e2a17-1aad-4745-9714-0131151c342f","html_url":"https://github.com/Terieyenike/SQL-notes","commit_stats":null,"previous_names":["terieyenike/sql-notes"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Terieyenike/SQL-notes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Terieyenike%2FSQL-notes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Terieyenike%2FSQL-notes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Terieyenike%2FSQL-notes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Terieyenike%2FSQL-notes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Terieyenike","download_url":"https://codeload.github.com/Terieyenike/SQL-notes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Terieyenike%2FSQL-notes/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262969883,"owners_count":23392529,"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":["postgresql","sql"],"created_at":"2024-11-19T22:37:22.972Z","updated_at":"2025-07-01T13:07:23.502Z","avatar_url":"https://github.com/Terieyenike.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# writing PSQL commands\n\n`CREATE EXTENSION`\n\n## creating a new database**\n\n`CREATE DATABASE database_name;`\n\n`createdb database_name` \n\n\n## ways to connect to a database\n\n1. `psql -h localhost -p 5432 -U teyenike database_name`\n1. `\\c database_name;`\n1. \\conninfo - showing you your current info\n1. psql -U user database_name\n\n**delete a database**\n\n`DROP DATABASE database_name;`\n\n**delete a table_name**\n\n`DROP TABLE table_name;`\n\n**create tables, DATA TYPES**\n\n```sql\nCREATE TABLE table_name (\n  id INT,\n  first_name VARCHAR(50),\n  last_name VARCHAR(50),\n  gender VARCHAR(6),\n  date_of_birth TIMESTAMP\n);\n```\n\n```sql\nCREATE TABLE student (\nstudent_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),\nfirst_name VARCHAR(255) NOT NULL,\nlast_name VARCHAR(255) NOT NULL,\nemail VARCHAR(255) NOT NULL,\ndate_of_birth DATE NOT NULL\n);\n```\n\n**CREATE AN EXTENSION**\n\nThese are pieces of software that allow you to expand what postgres can do or expand how certain processes run\n\n`CREATE extension IF NOT EXISTS \"uuid-ossp\"`\n\n**list of all tables in a database**\n\n`\\d`\n\n**describe the actual table name**\n\n`\\d table_name;`\n\n**show schemas**\n\n`\\dn`\n\n**view roles**\n\n\\du\n\n**Exit in the terminal**\n\n`\\q`\n\n**show all databases**\n\n`\\l`\n\n**Show help on backslash commands**\n\n`\\?`\n\n![table with constraints](psql.png \"table with constraints\")\n\n**see just table**\n\n`\\dt`\n\n\n## Insert data into a table\n\n```sql\nINSERT INTO person (first_name, last_name, gender, date_of_birth)\nVALUES (\"Teri\", \"Eyenike\", \"Male\", date \"1991-07-15\");\n```\n\nNeed some data for your project\n\n[Mockaroo](https://mockaroo.com \"Random data generator and API mocking tool\")\n\n## execute commands from file with `\\i`\n\n```sql\n-- switch into the database\n\n\\i /Users/teyenike/folder_destination/file_name.sql\n```\n\n## ORDER BY\n\n```SQL\nSELECT *\nFROM table_name\nORDER BY query ASC/DESC\n;\n```\n\n## also the same as LIMIT\n\n```sql\nSELECT *\nFROM person\nOFFSET 5\nFETCH FIRST 5\nROW ONLY\n;\n```\n\n## IN\n\n```sql\nSELECT *\nFROM person\nWHERE country_of_birth IN ('China', 'France', 'Brazil')\n;\n```\n\n## IGNORE CASE SENSITIVE\n\n```sql\nSELECT *\nFROM person\nWHERE country_of_birth ILIKE 'p%';\n```\n\n## GROUP BY\n\n```sql\nSELECT country_of_birth, COUNT(*)\nFROM person\nGROUP BY country_of_birth\nORDER BY country_of_birth ASC;\n```\n\n## GROUP BY HAVING\n\n```sql\nSELECT country_of_birth, COUNT(*)\nFROM person\nGROUP BY country_of_birth\nHAVING COUNT(*) \u003e 10\nORDER BY country_of_birth;\n```\n\nMAX, MIN, AVG\n\n```sql\nSELECT MAX(price)\nFROM car\n\nSELECT MIN(price)\nFROM car\n\nSELECT AVG(price)\nFROM car\n\nSELECT ROUND(AVG(price))\nFROM car\n```\n\nCOALESCE\n_default value in case the first one is not present._\n\n```SQL\nSELECT COALESCE(email, 'Email not provided')\nFROM person\n```\n\nHANDLE DIVISION BY ZERO\n\n```sql\nSELECT COALESCE(10 / NULLIF(0, 0), 0)\n```\n\nDATE\n\n```sql\nSELECT NOW();\n\nSELECT NOW()::DATE;\n\nSELECT NOW()::TIME;\n```\n\nADDING AND SUBTRACTING WITH DATES\n\n```sql\nSELECT NOW() - INTERVAL '1 YEAR'\n\nSELECT (NOW() + INTERVAL '10 MONTHS')::DATE;\n```\n\nEXTRACTING FIELDS\n\n```sql\nSELECT EXTRACT(MONTH FROM NOW());\n\nSELECT EXTRACT(YEAR FROM NOW());\n\nSELECT EXTRACT(DAY FROM NOW());\n\nselect extract(day from date '1991-07-15') as Day;\n\nselect extract(month from date '1991-07-15') as Month;\n\nselect extract(year from date '1991-07-15') as Year;\n\n# DAY OF THE WEEK\nSELECT EXTRACT(DOW FROM NOW());\n\nSELECT EXTRACT(CENTURY FROM NOW());\n```\n\n# ROUND A DATE\n\nto start from the beginning of the year 01-01\n\n```sql\nSELECT DATE_TRUNC('year', date '1991-07-15')\n```\n\n## AGE FUNCTION\n\n```sql\n# calculate the age of your birth from the actual date.\nSELECT first_name,\n      last_name,\n      date_of_birth,\n      AGE(NOW(), date_of_birth) AS age\n      FROM person\n      ;\n```\n\n## DELETE A RECORD FROM OUR TABLE\n\n```sql\nDELETE FROM person\nWHERE id = 1;\n```\n\n## UPDATE A LIST ON TABLE\n\n```sql\nSELECT *\nFROM person\nUPDATE person SET email = 'teri@gmail.com'\nWHERE id = 7\n;\n\n# OR update multiple data at once\n\nUPDATE person SET\nfirst_name='Achim',\nlast_name='Eyenike',\nemail = 'codegod@gmail.com'\nWHERE id = 2007\n```\n\n## GENERATE CSV WITH POSTGRES\n\n```SQL\n\\copy (SELECT *\n  FROM table_name\n  LEFT JOIN car\n  ON car.id = person.car_id)\n  TO '/Users/teyenike/Documents/result.csv' DELIMITER ',' CSV HEADER\n```\n\n```sql\n/*\ncopy all the data from the employees\ntable into a csv file\n*/\nCOPY (SELECT *\n  FROM employees)\n  TO '/Users/oterieyenike/Downloads/result.csv' DELIMITER ',' CSV HEADER\n```\n\n```sql\nCOPY capitals (id, country, capital)\nFROM '/Users/oterieyenike/Downloads/capitals.csv'\nDELIMITER ','\nCSV HEADER;\n```\n\n## INSTALL EXTENSION IN POSTGRES\n\n```sql\nCREATE EXTENSION\nIF NOT EXISTS\n\"uuid-assp\"\n```\n\n## Understanding SQL and DataBases\n\nStructured Query Language (SQL) is a query language that have existed since 1974. It's a powerful and easy to learn. SQL is what we would be using to query our database, Postgres. That is, Postgres uses SQL as its main query language. The best way to learn how to write a query language is not by using a Graphical User Interface (GUI) but rather we would be writing all our query in an interactive shell called psql or better still in our terminal or command line for Window users.\n\n**What is a Database?**\n\nA database is used to store, manipulate, and retrieve data stored in tables. SQL helps us to manage data held in a relational database.\n\n**History and story of Data**\nDatabase is a collection of data, a method for accessing and manipulating that data. Data is everywhere. Data is the most valueable commodity in the world. That is why big companies are very particular about this. Everyday in our world, we produce data whether it's drones with footages or location data, mobile phone apps, CCTV, websites.\nTo summarize, databases is simply to capture data and they are just computers comprising of the hardware (mechanical parts) and software (code written to query its data).\nA database is a diskdrive, a way to store 1s and 0s on our computer.\n\n**What Databases can solve**\n\n- Automate tasks\n- Making sure DB has integrity that is nobody can modify and/or delete the database.\n- Combine databases.\n\n**Fields that databases are useful to**\n\n1. Product managers - always know the product they are working on.\n2. Marketers - to find information to analyse business decisions, give insights on how to market the product.\n3. Web Developers\n4. Data Analyst\n5. Data Engineers/Administrators\n\n**DataBase Management System (DBMS)**\n\nA software or program used to manage the database.\n\n**Relational DataBase Management System**\nThis is more specific which is a subset of DBMS. Examples of RDBMS are PostgreSQL, MariaDB, ElasticSearch, SQLite, MySQL etc.\n\nSQL is declarative language. Meaning it is stating what will happen. The original name for SQL was Sequel meaning Structured English Query Language. Technically in 1970s but formalized in 1980s.\n\n**Terminologies**\n\n**Columns**\n\nDegree - A collection of columns.\n\nDomain/Constraint - It is what a particular column can store.\n\nAttributes - My domain has these attributes.\n\n**Rows**\n\nRows - Inserting data into tables when creating rows.\n\nTuple/Row - A single record of data.\n\nTuples/rows - Multiple rows of data.\n\nCardinality - collection of rows/tuples.\n\n**Primary and Foreign keys**\n\nPrimary key - It is a unique identifier\n\nForeign key - It is a key that would reference the primary key, the unique identifier of a different table. Relationship between two pieces of data.\n\n**PS**: we link relationship by a primary key.\n\n## Definition of Terms\n\nOLTP - Online Transaction Processing. It support and drive the day to day business.\n\nOLAP - Online Analytical Processing. It support analysis and drive future decisions.\n\n# SQL Deep Dive\n\nSQL commands are categorized into four categories.\n\n- Data Definition Language\n- Data Control Language\n- Data Manipulation Language\n- Data Query Language\n\n## What is Select?\n\nSelect is a SQL command used to retrieve or get data filtering the information by row.\n\n```sql\npsql -U postgres -d Employees \u003c employees.sql\n```\n\n## Renaming columns\n\n```sql\nSELECT column AS \"\u003cnew name\u003e\" from table-name\n```\n\n## Column Concatenation\n\nMake your data prettier/simpler and concatenate columns together.\n\nWhen using the Concat function make use of single quote (represents text, character) and rename columns with the AS keyword.\n\nDouble quote represent column name, tables.\nSingle quote refers to characters.\n\n```sql\nSELECT CONCAT(emp_no, ' is a ', title)\nAS \"Employee Title\"\nFROM titles\n\nOR\n\nSELECT emp_no, CONCAT(first_name, ' ', last_name)\nAS \"full name\"\nFROM employees\n```\n\n## What is a Function\n\nSet of steps that creates a single value.\n\n**Types**\n\n- Aggregate functions\n\nIt takes all its data and produce a single value.\nhttps://www.postgresql.org/docs/12/functions-aggregate.html\n\nOr\n\nOperate on many records to produce one value.\n\nExamples of some aggregate functions include, count(), sum(), max(), min(), avg()\n\n```\nSELECT count(colum_name) FROM employees;\n```\n\n![aggregate function](./sql3.png)\n\n- Scalar (non-aggregate functions)\n\nOperate on each record independently\n\n\u003c!-- Comment --\u003e\n\n### Comment in SQL\n\n[How To Make Comments](https://www.red-gate.com/simple-talk/sql/oracle/how-to-make-comments-the-most-important-code-you-write/)\n\n```\n--- single line comment\n\n/*\nmulti-line comments\n*/\n```\n\n## Filter on a single column with the `AND` keyword.\n\n`AND`\n\n```sql\nSELECT col1, col2 FROM table_name\nWHERE col1 = 'Expression' AND col2 = \"Expression\"\n```\n\n`AND and OR`\n\n```sql\nSELECT first_name, last_name, hire_date\n from employees where first_name = 'Georgi' AND last_name = 'Facello' AND hire_date = '1986-06-26'\n OR first_name = 'Bezalel' AND last_name = 'Simmel';\n```\n\n```sql\nselect firstname, lastname, gender, state\nfrom customers where (state = 'OR' OR state = 'NY')\nAND gender = 'F';\n```\n\n`WHERE` - Order of operation\n\n`OR` - Start a new filter.\n\n`AND` - chain together multiple criteria.\n\n`NOT keyword`\n\nfilter everything But exclusion of this. Remove things from the result we don't want.\n\n```sql\nselect age from customers where not age = 55;\n```\n\n\u003chr/\u003e\n\n## Commenting your queries\n\nDescribe what's happening in your written code.\n\n## Operator Precedence\n\nA statement having multiple operators is evaluated based on the priority of operators.\n\nParentheses -\u003e multiplication/division -\u003e Subtraction/addition -\u003e NOT -\u003e AND -\u003e OR\n\n![precedence](./precedence.png)\n\n`IS operator`\n\nallows you to filter on values that are null, not null, true, or false.\n\n## NULL Coalescing\n\nNull value substitution - ability to replace null values to operate on the data.\n\nCoalesce returns the first non-null value in a list.\n\n## 3 valued logic\n\n```sql\nSELECT *\nFROM customers\nWHERE address2 IS NOT null;\n```\n\n```sql\nSELECT coalesce(lastName, 'Empty'), * from \"Student\"\nwhere (age IS NULL);\n```\n\n`BETWEEN AND`\n\nShorthan to match against a range of values. It is sensitive to the order of the arguments.\n\nWhy should we use it?\n\n- Readable\n- Maintainable\n\n`IN keyword`\n\nFiltering multiple values. Check if a value matches any value in a list of values.\n\n```sql\nSELECT COUNT(orderid)\nFROM orders\nWHERE customerid IN (7888, 1082, 12808, 9623)\n```\n\n```sql\nSELECT COUNT(id)\nFROM city\nWHERE district IN ('Zuid-Holland', 'Noord-Brabant', 'Utrecht');\n```\n\n## Like - Partial Lookups\n\nWhat if you don't know exactly what you're looking for? The LIKE keyword helps\n\n**Pattern matching**\n\nIn order to use LIKE you need to build patterns to match. It happens with wildcards.\n\n% - any number of characters\n\n\\_ one character after\n\n| Pattern | Description                                                                |\n| ------- | -------------------------------------------------------------------------- |\n| '%x'    | Any value that ends with the letter x.                                     |\n| 'x%'    | Any value that starts with the letter x.                                   |\n| '%x%'   | Any value that has the letter x in any position.                           |\n| 'x%z'   | Any value that starts with the letter x and ends with the letter z.        |\n| '\\_x%'  | Any value that has the letter x in the second position.                    |\n| 'x*%*%' | Any value that starts with the letter x and has at least three characters. |\n\n**Casting** is the act of changing something to something else.\n\n```\nfirst method: CAST(Salary AS text)\n\nsecond method: salary::text\n```\n\n```sql\nselect * from customers\nwhere CAST(zip as TEXT) LIKE '%2%'\n```\n\n**Random**\n\n```sql\nSELECT emp_no,\nfirst_name,\nEXTRACT (YEAR FROM AGE(birth_date)) as \"age\"\nFROM employees\nWHERE first_name ILIKE 'M%';\n```\n\n```sql\nselect coalesce(state, 'No State') as \"State\"\nfrom customers\nwhere phone::text\nLIKE '302%';\n```\n\n\u003chr /\u003e\n\n## Set the timezone for all of the session for the user you log in with.\n\n```sql\nALTER USER user SET timezone = 'UTC'\n\nSHOW timezone;\n```\n\n`user` here means the user on the mac\n\n## Alter a table - add missing information to table\n\nChange the SCHEMA of a table\nChange the name of a table-level CONSTRAINT\nAdd and remove constraints\nChange a column level constraint\n\n```sql\nALTER TABLE \u003ctable_name\u003e\nADD COLUMN \u003ccolumn_name\u003e data_type\n\nALTER TABLE course\nALTER COLUMN teacher_id\nSET NOT null;\n```\n\n## TimeStamps\n\nTimestamp is a date with time and timezone info.\n\nPostgresql uses the ISO-8601 as a standard in timezone formatting.\n\nYYYY:MM:DDTHH:MM:SS\n\n2020:09:09T11:13:54+02:00\n\n```sql\nSELECT NOW()::date;\n\nSELECT CURRENT_DATE;\n\n```\n\n## Formatting Date Functions\n\n```sql\nSELECT TO_CHAR(CURRENT_DATE, 'dd/mm/yyyy');\n```\n\n`DISTINCT keyword`\n\nIt removes duplicates. The DISTINCT clause keeps one row for each group of duplicates.\n\n`ORDER BY and ORDER BY LENGTH keyword`\n\n## Sorting data\n\nSort data either ASCENDING (ASC) or DESCENDING (DESC) by columns. The command applies to the right most value and applies ASC to a column when not specified.\n\n```sql\n  SELECT first_name, last_name from employees ORDER BY first_name, last_name DESC;\n\n  OR\n\n  SELECT first_name, last_name from employees ORDER BY LENGTH(first_name), last_name ASC;\n```\n\n# ADVANCED SQL\n\n**GROUP BY** clause\n\nSummarize or aggregate data by groups. Why is it important?\n\nTo get in-depth information by group.\n\nGROUP BY splits data groups or chunks so we can apply functions against the group rather than the entire table.\n\nWe use GROUP BY almost exclusively with aggregate functions. When we GROUP BY we apply the function per group, not on the entire data set.\n\nPS. ORDER BY happens last of the GROUP BY clause.\n\n```sql\nSELECT select_list COUNT(select_list)\nFROM select_list\nGROUP BY select_list;\n\nSELECT select_list, COUNT(select_list)\nfrom select_list\nwhere select_list = 'Expression'\ngroup by select_list\n\n```\n\n**Things to remember**\n\nEvery column not in the GROUP BY clause must apply a function. GROUP BY is stricter than it looks. Why?\n\nIt's to reduce all records found for the matching GROUP to a single record.\n\nGROUP BY utilizes a Split-Apply-Combine strategy.\n\n**Split Phase**\n\nDivide into groups with values.\n\n**Apply Phase**\n\nApply aggregate against ungrouped columns.\n\n**Combine Phase**\n\nCombine groups with a single value into a single value.\n\n## Order of precedence - order SQL to do something.\n\n`FROM -\u003e WHERE -\u003e GROUP BY -\u003e SELECT -\u003e ORDER`\n\nWHERE GROUP BY - after the WHERE clause\n\nFROM GROUP BY - when there is no WHERE clause.\n\n**HAVING** clause\n\nThe major difference between WHERE and HAVING clause is\n\nWHERE applies filters to individual rows.\n\nHAVING applies filters to a group as a whole.\n\n## Order of precedence\n\n`FROM -\u003e WHERE -\u003e GROUP BY -\u003e HAVING -\u003e SELECT -\u003e ORDER`\n\n\u003chr /\u003e\namigoscode\n\n## What is a Relational Database?\n\nRelational database is a relation between one or more tables. The major benefit of using a relational database is to help us split information in tables and have a relationship between them.\n\nBefore we go further into writing our first query, we need to know how data is stored.\n\n1. Data is stored in tables\n2. Columns\n3. Rows\n\n**PostgreSQL**\n\n- Object-relatioal database management system\n- Modern\n- Open Source\n\n**Other options**\nOracle database, MySql, Microsoft SQL Server\n\n\u003e AND: This operator makes sure both sides of the operator (both conditions) are true.\n\u003e • OR: This operator makes sure one side at least of the operator is true.\n\u003e • NOT: This operator makes sure that the condition following this operator is false.\n\n## INNER JOIN\n\n```sql\nSELECT [Column List]\n  FROM [Table 1] INNER JOIN [Table 2]\n    ON [Table 1 Column Name] = [Table 2 Column Name]\nWHERE [Condition]\n```\n\n\u003csmall\u003eINNER in the query is optional\u003c/small\u003e\n\n## RIGHT JOIN\n\n```sql\nSELECT [Column List]\n  FROM [Table 1] RIGHT OUTER JOIN [Table 2]\n    ON [Table 1 Column Name] = [Table 2 Column Name]\nWHERE [Condition]\n\n\nSELECT [Column List]\n  FROM [Table 1] RIGHT JOIN [Table 2]\n    ON [Table 1 Column Name] = [Table 2 Column Name]\nWHERE [Condition]\n```\n\n\u003csmall\u003eOUTER in the query is optional\u003c/small\u003e\n\n## CROSS JOIN\n\n```sql\nSELECT [Column List]\n  FROM [Table 1] CROSS JOIN [Table 2]\nWHERE [Condition]\n```\n\n## UNION JOIN\n\nThe UNION operation is used to combine two queries.\n\n```sql\nSELECT [COLUMNS LIST] FROM [TABLE NAME]\nUNION\nSELECT [COLUMNS LIST] FROM [TABLE NAME]\n```\n\nHowever, the most important point to remember when we use the UNION operation is to ensure the following:\n• Both query columns have similar data types\n• Both query columns are in the same order\n\n## Window of Functions\n\nWindow functions create a new column based on functions performed on a subset or window of data. To apply window of functions, the keyword `OVER` is necessary.\n\n```psql\nSELECT *, MAX(salary) OVER()\nFROM salaries\nWHERE salary \u003c 70000;\n```\n\nWindow of data, data that the query calculated out not what limit cut off. It is what the query returns itself.\n\nFilter - of all of the data got, show me this.\n\nlimit - the query is still returning everything, cut it off at this number.\n\n## PARTITION BY\n\nDivide rows into groups to apply the function against (optional).\n\n```psql\nSELECT *, AVG(salary) OVER(PARTITION BY d.dept_name)\nFROM salaries\nJOIN dept_emp AS de USING (emp_no)\nJOIN departments AS d USING (dept_no)\n```\n\n## ORDER BY\n\nOrder the results. Order By has a special property called `Framing`. It changes the frame of the window function.\n\n```psql\nSELECT *, COUNT(salary)\nOVER(ORDER BY emp_no)\nFROM salaries\n```\n\n# Exercises\n\n```sql\n/*\n* DB: Store\n* Table: orders\n* Question: Get all orders from customers who live in Ohio (OH), New York (NY) or Oregon (OR) state\n* ordered by orderid\n*/\n\nSELECT c.firstname, c.lastname, o.orderid FROM orders AS o\nINNER JOIN customers AS c ON o.customerid = c.customerid\nWHERE c.state IN ('NY', 'OH', 'OR')\nORDER BY o.orderid;\n\n\n/*\n* DB: Store\n* Table: products\n* Question: Show me the inventory for each product\n*/\n\nSELECT p.prod_id, i.quan_in_stock\nFROM products as p\nINNER JOIN inventory AS i oN p.prod_id = i.prod_id\n\n\n/*\n* DB: Employees\n* Table: employees\n* Question: Show me for each employee which department they work in\n*/\n\nSELECT e.first_name, dp.dept_name\nFROM employees AS e\nINNER JOIN dept_emp AS de ON de.emp_no = e.emp_no\nINNER JOIN departments AS dp ON dp.dept_no = de.dept_no\n```\n\n## Group BY Exercise\n\n```sql\n/*\n*  How many people were hired on did we hire on any given hire date?\n*  Database: Employees\n*  Table: Employees\n*/\n\nSELECT a.hire_date, COUNT(b.hire_date) as \"amount\"\nFROM employees as a, employees as b\nWHERE a.hire_date = b.hire_date\nGROUP BY a.hire_date\nORDER BY \"amount\" DESC;\n\n/*\n*  Show me all the employees, hired after 1991, that have had more than 2 titles\n*  Database: Employees\n*/\n\nSELECT e.emp_no, count(t.title) as \"amount of titles\"\nFROM employees as e\nJOIN titles as t USING(emp_no)\nWHERE EXTRACT (YEAR FROM e.hire_date) \u003e 1991\nGROUP BY e.emp_no\nHAVING count(t.title) \u003e 2\nORDER BY e.emp_no;\n\n/*\n*  Show me all the employees that have had more than 15 salary changes that work in the department development\n*  Database: Employees\n*/\n\nSELECT e.emp_no, count(s.from_date) as \"amount of raises\"\nFROM employees as e\nJOIN salaries as s USING(emp_no)\nJOIN dept_emp AS de USING(emp_no)\nWHERE de.dept_no = 'd005'\nGROUP BY e.emp_no\nHAVING count(s.from_date) \u003e 15\nORDER BY e.emp_no;\n\n/*\n*  Show me all the employees that have worked for multiple departments\n*  Database: Employees\n*/\n\nSELECT e.emp_no, count(de.dept_no) as \"worked for # departments\"\nFROM employees as e\nJOIN dept_emp AS de USING(emp_no)\nGROUP BY e.emp_no\nHAVING count(de.dept_no) \u003e 1\nORDER BY e.emp_no;\n```\n\n## Window function exercise\n\n```sql\n\n/*\n*  Show the population per continent\n*  Database: World\n*  Table: Country\n*/\nSELECT\n  DISTINCT continent,\nSUM(population) OVER w1 as\"continent population\"\nFROM country\nWINDOW w1 AS( PARTITION BY continent );\n/*\n*  To the previous query add on the ability to calculate the percentage of the world population\n*  What that means is that you will divide the population of that continent by the total population and multiply by 100 to get a percentage.\n*  Make sure you convert the population numbers to float using `population::float` otherwise you may see zero pop up\n*\n*  Database: World\n*  Table: Country\n*/\nSELECT\n  DISTINCT continent,\nSUM(population) OVER w1 as\"continent population\",\n  CONCAT(\n      ROUND(\n          (\nSUM( population::float4 ) OVER w1 /\nSUM( population::float4 ) OVER()\n          ) * 100\n      ),'%' ) as \"percentage of population\"\nFROM country\nWINDOW w1 AS( PARTITION BY continent );\n/*\n*  Count the number of towns per region\n*\n*  Database: France\n*  Table: Regions (Join + Window function)\n*/\nSELECT\nDISTINCT r.id,\nr.\"name\",\nCOUNT(t.id) OVER (\n    PARTITION BY r.id\nORDER BY r.\"name\"\n) AS \"# of towns\"\nFROM regions AS r\nJOIN departments AS d ON r.code = d.region\nJOIN towns AS t ON d.code = t.department\nORDER BY r.id;\n```\n\n## Conditional statements\n\n```sql\n/**\n* Database: Store\n* Table: products\n* Create a case statement that's named \"price class\" where if a product is over 20 dollars you show 'expensive'\n* if it's between 10 and 20 you show 'average'\n* and of is lower than or equal to 10 you show 'cheap'.\n*/\n\nSELECT prod_id, title, price,\n    CASE\n      WHEN  price \u003e 20 THEN 'expensive'\n      WHEN  price \u003c= 10 THEN  'cheap'\n      WHEN  price BETWEEN 10 and 20  THEN 'average'\n    END AS \"price class\"\nFROM products\n```\n\n## NULLIF exercise\n\n```sql\n\n/*\n* DB: Store\n* Table: products\n* Question: Show NULL when the product is not on special (0)\n*/\n\nSELECT prod_id, title, price,\nNULLIF(special, 0) as \"special\"\nFROM products\n```\n\n## View exercise\n\n```sql\n/*\n*  Create a view \"90-95\" that:\n*  Shows me all the employees, hired between 1990 and 1995\n*  Database: Employees\n*/\n\nCREATE VIEW \"90-95\" AS\nSELECT *\nFROM employees as e\nWHERE EXTRACT (YEAR FROM e.hire_date) BETWEEN 1990 AND 1995\nORDER BY e.emp_no;\n\n/*\n*  Create a view \"bigbucks\" that:\n*  Shows me all employees that have ever had a salary over 80000\n*  Database: Employees\n*/\n\nCREATE VIEW \"bigbucks\" AS\nSELECT e.emp_no, s.salary\nFROM employees as e\nJOIN salaries as s USING(emp_no)\nWHERE s.salary \u003e 80000\nORDER BY s.salary;\n```\n\n## Subquery exercises\n\n```sql\n\n/* TRY TO WRITE THESE AS JOINS FIRST */\n/*\n* DB: Store\n* Table: orders\n* Question: Get all orders from customers who live in Ohio (OH), New York (NY) or Oregon (OR) state\n* ordered by orderid\n*/\nSELECT c.firstname, c.lastname, o.orderid\nFROM orders AS o, (\nSELECT customerid, state, firstname, lastname\nFROM customers\n) AS c\nWHERE  o.customerid = c.customerid AND\nc.state IN ('NY', 'OH', 'OR')\nORDER BY o.orderid;\n/*\n* DB: Employees\n* Table: employees\n* Question: Filter employees who have emp_no 110183 as a manager\n*/\nSELECT emp_no, first_name, last_name\nFROM employees\nWHERE emp_no IN (\nSELECT emp_no\nFROM dept_emp\nWHERE dept_no = (\nSELECT dept_no\nFROM dept_manager\nWHERE emp_no = 110183\n    )\n)\nORDER BY emp_no\n-- Written with JOIN\nSELECT e.emp_no, first_name, last_name\nFROM employees as e\nJOIN dept_emp as de USING (emp_no)\nJOIN dept_manager as dm USING (dept_no)\nWHERE dm.emp_no = 110183\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterieyenike%2Fsql-notes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterieyenike%2Fsql-notes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterieyenike%2Fsql-notes/lists"}