├── Intermediate SQL ├── Readme_Dataset ├── 4. Window Functions.pdf ├── 1. We'll Take The Case.pdf ├── 2. Short and Simple Subqueries.pdf ├── 3. Correlated Queries, Nested Queries, and Common Table Expressions.pdf ├── 2. Short and Simple Subqueries.sql ├── 4. Window Functions.sql ├── 3. Correlated Queries, Nested Queries, and Common Table Expressions.sql └── 1. We'll Take The Case.sql ├── Joining Data in SQL ├── 4) Subqueries.pdf ├── DATASET │ ├── diagrams.zip │ ├── leaders2.zip │ └── countries2.zip ├── 3) Set theory clauses.pdf ├── 1) Introduction to joins.pdf ├── 2) Outer joins and cross joins.pdf ├── 3) Set theory clauses.sql └── 4) Subqueries.sql ├── PostgreSQL Summary Stats and Window Functions ├── 4.Beyond Window Functions.pdf ├── 2.Fetching, ranking, and paging.pdf ├── 1.Introduction To Window Functions.pdf ├── 3.Aggregate window functions and frames.pdf ├── 2.Fetching, ranking, and paging.sql ├── 1.Introduction To Window Functions.sql ├── 3.Aggregate window functions and frames.sql └── 4.Beyond Window Functions.sql ├── Functions for Manipulating Data in PostgreSQL ├── 1.Overview of Common Data Types.pdf ├── 3.Parsing and Manipulating Text.pdf ├── 4.Full-text Search and PostgresSQL Extensions.pdf ├── 2.Working with DATE-TIME Functions and Operators.pdf ├── 1.Overview of Common Data Types.sql ├── 3.Parsing and Manipulating Text.sql ├── 4.Full-text Search and PostgresSQL Extensions.sql ├── DATASET │ └── postgres-sakila-incremental-schema_06172019.sql └── 2.Working with DATE-TIME Functions and Operators.sql └── README.md /Intermediate SQL/Readme_Dataset: -------------------------------------------------------------------------------- 1 | There is no data set is provided for this 'Intermediate SQL' Course by Datacamp.org 2 | -------------------------------------------------------------------------------- /Joining Data in SQL/4) Subqueries.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Joining Data in SQL/4) Subqueries.pdf -------------------------------------------------------------------------------- /Intermediate SQL/4. Window Functions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Intermediate SQL/4. Window Functions.pdf -------------------------------------------------------------------------------- /Joining Data in SQL/DATASET/diagrams.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Joining Data in SQL/DATASET/diagrams.zip -------------------------------------------------------------------------------- /Joining Data in SQL/DATASET/leaders2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Joining Data in SQL/DATASET/leaders2.zip -------------------------------------------------------------------------------- /Intermediate SQL/1. We'll Take The Case.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Intermediate SQL/1. We'll Take The Case.pdf -------------------------------------------------------------------------------- /Joining Data in SQL/DATASET/countries2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Joining Data in SQL/DATASET/countries2.zip -------------------------------------------------------------------------------- /Joining Data in SQL/3) Set theory clauses.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Joining Data in SQL/3) Set theory clauses.pdf -------------------------------------------------------------------------------- /Joining Data in SQL/1) Introduction to joins.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Joining Data in SQL/1) Introduction to joins.pdf -------------------------------------------------------------------------------- /Intermediate SQL/2. Short and Simple Subqueries.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Intermediate SQL/2. Short and Simple Subqueries.pdf -------------------------------------------------------------------------------- /Joining Data in SQL/2) Outer joins and cross joins.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Joining Data in SQL/2) Outer joins and cross joins.pdf -------------------------------------------------------------------------------- /PostgreSQL Summary Stats and Window Functions /4.Beyond Window Functions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/PostgreSQL Summary Stats and Window Functions /4.Beyond Window Functions.pdf -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/1.Overview of Common Data Types.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Functions for Manipulating Data in PostgreSQL/1.Overview of Common Data Types.pdf -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/3.Parsing and Manipulating Text.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Functions for Manipulating Data in PostgreSQL/3.Parsing and Manipulating Text.pdf -------------------------------------------------------------------------------- /PostgreSQL Summary Stats and Window Functions /2.Fetching, ranking, and paging.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/PostgreSQL Summary Stats and Window Functions /2.Fetching, ranking, and paging.pdf -------------------------------------------------------------------------------- /PostgreSQL Summary Stats and Window Functions /1.Introduction To Window Functions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/PostgreSQL Summary Stats and Window Functions /1.Introduction To Window Functions.pdf -------------------------------------------------------------------------------- /Intermediate SQL/3. Correlated Queries, Nested Queries, and Common Table Expressions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Intermediate SQL/3. Correlated Queries, Nested Queries, and Common Table Expressions.pdf -------------------------------------------------------------------------------- /PostgreSQL Summary Stats and Window Functions /3.Aggregate window functions and frames.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/PostgreSQL Summary Stats and Window Functions /3.Aggregate window functions and frames.pdf -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/4.Full-text Search and PostgresSQL Extensions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Functions for Manipulating Data in PostgreSQL/4.Full-text Search and PostgresSQL Extensions.pdf -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/2.Working with DATE-TIME Functions and Operators.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Novartus/Datacamp_SQL/HEAD/Functions for Manipulating Data in PostgreSQL/2.Working with DATE-TIME Functions and Operators.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SQL Fundamentals 2 | 3 |

4 | 5 |

6 | 7 | 8 | It contains the SQL solution of the following tracks with DataSet. 9 | - Joining Data In SQL 10 | - Intermediate SQL 11 | - PostgreSQL Summary Stats and Window Functions 12 | - Functions for Manipulating Data in PostgreSQL -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/1.Overview of Common Data Types.sql: -------------------------------------------------------------------------------- 1 | /* 2 | -- Text data types 3 | Q: Which of the following is not a valid text data type in PostgreSQL? 4 | A: STRING 5 | */ 6 | 7 | /* 8 | In relational databases, the information schema is an ANSI-standard set of read-only views which provide information about all of the tables, views, columns, and procedures in a database. 9 | */ 10 | 11 | -- Getting information about your database 12 | -- (1) 13 | SELECT * 14 | FROM INFORMATION_SCHEMA.TABLES 15 | WHERE table_schema = 'public'; 16 | 17 | -- (2) 18 | SELECT * 19 | FROM INFORMATION_SCHEMA.COLUMNS 20 | WHERE table_name = 'actor'; 21 | 22 | -- Determining data types 23 | SELECT 24 | column_name, 25 | data_type 26 | FROM INFORMATION_SCHEMA.COLUMNS 27 | -- For the customer table 28 | WHERE table_name = 'customer'; 29 | 30 | /* 31 | -- Properties of date and time data types 32 | Q: Which of the following is NOT correct? 33 | A: TIME data types are stored with a timezone by default. 34 | */ 35 | 36 | -- Interval data types 37 | SELECT 38 | rental_date, 39 | return_date, 40 | rental_date + INTERVAL '3 days' AS expected_return_date 41 | FROM rental; 42 | 43 | -- Accessing data in an ARRAY 44 | -- (1) 45 | SELECT 46 | title, 47 | special_features 48 | FROM film; 49 | 50 | -- (2) 51 | SELECT 52 | title, 53 | special_features 54 | FROM film 55 | 56 | -- (3) 57 | SELECT 58 | title, 59 | special_features 60 | FROM film 61 | WHERE special_features[2] = 'Deleted Scenes'; 62 | 63 | -- Searching an ARRAY with ANY 64 | SELECT 65 | title, 66 | special_features 67 | FROM film 68 | WHERE 'Trailers' = ANY (special_features); 69 | 70 | -- Searching an ARRAY with @> 71 | SELECT 72 | title, 73 | special_features 74 | FROM film 75 | WHERE special_features @> ARRAY['Deleted Scenes']; -------------------------------------------------------------------------------- /Joining Data in SQL/3) Set theory clauses.sql: -------------------------------------------------------------------------------- 1 | -- Union 2 | 3 | SELECT * 4 | FROM economies2010 5 | UNION 6 | SELECT * 7 | FROM economies2015 8 | ORDER BY CODE, YEAR; 9 | 10 | 11 | -- Union (2) 12 | SELECT country_code 13 | FROM cities 14 | UNION 15 | SELECT code 16 | FROM currencies 17 | Order BY country_code; 18 | 19 | -- Union all 20 | 21 | SELECT code, year 22 | FROM economies 23 | UNION ALL 24 | SELECT country_code, year 25 | FROM populations 26 | ORDER BY code, year; 27 | 28 | -- Intersect 29 | 30 | SELECT code, year 31 | FROM economies 32 | INTERSECT 33 | SELECT country_code, year 34 | FROM populations 35 | ORDER BY code, year; 36 | 37 | -- Intersect (2) 38 | 39 | SELECT name 40 | FROM countries 41 | INTERSECT 42 | SELECT name 43 | FROM cities; 44 | 45 | -- Review union and intersect 46 | -- Q:- Which of the following combinations of terms and definitions is correct? 47 | -- Ans:- INTERSECT: returns only records appearing in both tables 48 | 49 | -- Except 50 | 51 | SELECT name 52 | FROM cities 53 | EXCEPT 54 | SELECT capital 55 | FROM countries 56 | ORDER BY name; 57 | 58 | -- Except (2) 59 | 60 | SELECT capital 61 | FROM countries 62 | EXCEPT 63 | SELECT name 64 | FROM cities 65 | ORDER BY capital; 66 | 67 | -- Semi-join 68 | 1) 69 | SELECT country.code 70 | FROM countries AS country 71 | WHERE country.region = 'Middle East'; 72 | 73 | 2) 74 | SELECT DISTINCT lang.name 75 | FROM languages AS lang 76 | ORDER BY lang.name; 77 | 78 | -- Relating semi-join to a tweaked inner join 79 | Ans: DISTNICT 80 | 81 | -- Diagnosing problems using anti-join 82 | 1) 83 | SELECT COUNT(*) 84 | FROM countries 85 | WHERE continent = 'Oceania'; 86 | 87 | 2) 88 | SELECT c1.code, c1.name, c2.basic_unit AS currency 89 | FROM countries AS c1 90 | INNER JOIN currencies AS c2 91 | USING (code) 92 | WHERE continent = 'Oceania'; 93 | 94 | 3) 95 | SELECT c1.code, c1.name 96 | FROM countries AS c1 97 | WHERE c1.continent = 'Oceania' 98 | AND code NOT IN 99 | (SELECT code 100 | FROM currencies); 101 | 102 | -- Set theory challenge 103 | SELECT name 104 | FROM cities AS c1 105 | WHERE country_code IN 106 | ( 107 | SELECT e.code 108 | FROM economies AS e 109 | UNION 110 | SELECT c2.code 111 | FROM currencies AS c2 112 | EXCEPT 113 | SELECT p.country_code 114 | FROM populations AS p 115 | ); 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/3.Parsing and Manipulating Text.sql: -------------------------------------------------------------------------------- 1 | -- Concatenating strings 2 | -- (1) 3 | SELECT first_name || ' ' || last_name || ' <' || email || '>' AS full_email FROM customer 4 | 5 | -- (2) 6 | SELECT CONCAT(first_name, ' ', last_name, ' <', email, '>') AS full_email FROM customer 7 | 8 | -- Changing the case of string data 9 | SELECT 10 | UPPER(c.name) 11 | || ': ' || INITCAP(f.title) AS film_category, 12 | LOWER(f.description) AS description 13 | FROM 14 | film AS f 15 | INNER JOIN film_category AS fc 16 | ON f.film_id = fc.film_id 17 | INNER JOIN category AS c 18 | ON fc.category_id = c.category_id; 19 | 20 | -- Replacing string data 21 | SELECT 22 | REPLACE(title, ' ', '_') AS title 23 | FROM film; 24 | 25 | -- Determining the length of strings 26 | SELECT 27 | title, 28 | description, 29 | CHAR_LENGTH(description) AS desc_len 30 | FROM film; 31 | 32 | -- Truncating strings 33 | SELECT 34 | LEFT(description, 50) AS short_desc 35 | FROM 36 | film AS f; 37 | 38 | -- Extracting substrings from text data 39 | SELECT 40 | SUBSTRING(address FROM POSITION(' ' IN address)+1 FOR LENGTH(address)) 41 | FROM 42 | address; 43 | 44 | -- Combining functions for string manipulation 45 | SELECT 46 | SUBSTRING(email FOR POSITION('@' IN email)-1) AS username, 47 | SUBSTRING(email FROM POSITION('@' IN email)+1 FOR CHAR_LENGTH(email)) AS domain 48 | FROM customer; 49 | 50 | -- Padding 51 | -- (1) 52 | SELECT 53 | RPAD(first_name, LENGTH(first_name)+1) || last_name AS full_name 54 | FROM customer; 55 | 56 | -- (2) 57 | SELECT 58 | first_name || LPAD(last_name, LENGTH(last_name)+1) AS full_name 59 | FROM customer; 60 | 61 | -- (3) 62 | SELECT 63 | RPAD(first_name, LENGTH(first_name)+1) 64 | || RPAD(last_name, LENGTH(last_name)+2, ' <') 65 | || RPAD(email, LENGTH(email)+1, '>') AS full_email 66 | FROM customer; 67 | 68 | -- The TRIM function 69 | SELECT 70 | CONCAT(UPPER(c.name), ': ', f.title) AS film_category, 71 | TRIM(LEFT(description, 50)) AS film_desc 72 | FROM 73 | film AS f 74 | INNER JOIN film_category AS fc 75 | ON f.film_id = fc.film_id 76 | INNER JOIN category AS c 77 | ON fc.category_id = c.category_id; 78 | 79 | -- Putting it all together 80 | SELECT 81 | UPPER(c.name) || ': ' || f.title AS film_category, 82 | LEFT(description, 50 - 83 | POSITION( 84 | ' ' IN REVERSE(LEFT(description, 50)) 85 | ) 86 | ) 87 | FROM 88 | film AS f 89 | INNER JOIN film_category AS fc 90 | ON f.film_id = fc.film_id 91 | INNER JOIN category AS c 92 | ON fc.category_id = c.category_id; -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/4.Full-text Search and PostgresSQL Extensions.sql: -------------------------------------------------------------------------------- 1 | -- A review of the LIKE operator 2 | -- (1) 3 | SELECT * 4 | FROM film 5 | WHERE title LIKE 'GOLD%'; 6 | 7 | -- (2) 8 | SELECT * 9 | FROM film 10 | WHERE title LIKE '%GOLD'; 11 | 12 | -- (3) 13 | SELECT * 14 | FROM film 15 | WHERE title LIKE '%GOLD%'; 16 | 17 | -- What is a tsvector? 18 | SELECT to_tsvector(description) 19 | FROM film; 20 | 21 | -- Basic full-text search 22 | SELECT title, description 23 | FROM film 24 | WHERE to_tsvector(title) @@ to_tsquery('elf'); 25 | 26 | -- User-defined data types 27 | -- (1) 28 | CREATE TYPE compass_position AS ENUM ( 29 | 'North', 30 | 'West', 31 | 'South', 32 | 'East' 33 | ); 34 | 35 | -- (2) 36 | CREATE TYPE compass_position AS ENUM ( 37 | 'North', 38 | 'South', 39 | 'East', 40 | 'West' 41 | ); 42 | SELECT typname 43 | FROM pg_type 44 | WHERE typname='compass_position'; 45 | 46 | -- Getting info about user-defined data types 47 | -- (1) 48 | SELECT column_name, data_type, udt_name 49 | FROM INFORMATION_SCHEMA.COLUMNS 50 | WHERE table_name ='film' and column_name='rating'; 51 | 52 | -- (2) 53 | SELECT * 54 | FROM pg_type 55 | WHERE typname='mpaa_rating' 56 | 57 | -- User-defined functions in Sakila 58 | -- (1) 59 | SELECT 60 | f.title, 61 | r.rental_id, 62 | i.inventory_id 63 | FROM film as f 64 | INNER JOIN inventory AS i ON f.film_id=i.film_id 65 | INNER JOIN rental AS r on i.inventory_id=r.inventory_id 66 | 67 | -- (2) 68 | SELECT 69 | f.title, 70 | r.rental_id, 71 | i.inventory_id, 72 | inventory_held_by_customer(i.inventory_id) AS held_by_cust 73 | FROM film as f 74 | INNER JOIN inventory AS i ON f.film_id=i.film_id 75 | INNER JOIN rental AS r on i.inventory_id=r.inventory_id 76 | 77 | -- (3) 78 | SELECT 79 | f.title, 80 | r.rental_id, 81 | i.inventory_id, 82 | inventory_held_by_customer(i.inventory_id) as held_by_cust 83 | FROM film as f 84 | INNER JOIN inventory AS i ON f.film_id=i.film_id 85 | INNER JOIN rental AS r on i.inventory_id=r.inventory_id 86 | WHERE 87 | inventory_held_by_customer(i.inventory_id) IS NOT NULL 88 | 89 | -- Enabling extensions 90 | -- (1) 91 | CREATE EXTENSION IF NOT EXISTS pg_trgm; 92 | 93 | -- (2) 94 | SELECT * 95 | FROM pg_extension; 96 | 97 | -- Measuring similarity between two strings 98 | SELECT 99 | title, 100 | description, 101 | similarity(title, description) 102 | FROM film 103 | 104 | -- Levenshtein distance examples 105 | SELECT 106 | title, 107 | description, 108 | levenshtein(title, 'JET NEIGHBOR') AS distance 109 | FROM 110 | film 111 | ORDER BY 3 112 | 113 | -- Putting it all together 114 | -- (1) 115 | SELECT 116 | title, 117 | description 118 | FROM 119 | film 120 | WHERE 121 | to_tsvector(description) @@ 122 | to_tsquery('Astounding & Drama'); 123 | 124 | -- (2) 125 | SELECT 126 | title, 127 | description, 128 | similarity(description, 'Astounding Drama') 129 | FROM 130 | film 131 | WHERE 132 | to_tsvector(description) @@ 133 | to_tsquery('Astounding & Drama') 134 | ORDER BY 135 | similarity(description, 'Astounding Drama') DESC; -------------------------------------------------------------------------------- /PostgreSQL Summary Stats and Window Functions /2.Fetching, ranking, and paging.sql: -------------------------------------------------------------------------------- 1 | -- Future gold medalists 2 | WITH Discus_Medalists AS ( 3 | SELECT DISTINCT 4 | Year, 5 | Athlete 6 | FROM Summer_Medals 7 | WHERE Medal = 'Gold' 8 | AND Event = 'Discus Throw' 9 | AND Gender = 'Women' 10 | AND Year >= 2000) 11 | 12 | SELECT 13 | Year, 14 | Athlete, 15 | LEAD(Athlete,3) OVER (ORDER BY Year ASC) AS Future_Champion 16 | FROM Discus_Medalists 17 | ORDER BY Year ASC; 18 | 19 | -- First athlete by name 20 | WITH All_Male_Medalists AS ( 21 | SELECT DISTINCT 22 | Athlete 23 | FROM Summer_Medals 24 | WHERE Medal = 'Gold' 25 | AND Gender = 'Men') 26 | 27 | SELECT 28 | athlete, 29 | FIRST_VALUE(athlete) OVER ( 30 | ORDER BY athlete ASC 31 | ) AS First_Athlete 32 | FROM All_Male_Medalists; 33 | 34 | -- Last country by name 35 | WITH Hosts AS ( 36 | SELECT DISTINCT Year, City 37 | FROM Summer_Medals) 38 | 39 | SELECT 40 | Year, 41 | City, 42 | LAST_VALUE(City) OVER ( 43 | ORDER BY Year ASC 44 | RANGE BETWEEN 45 | UNBOUNDED PRECEDING AND 46 | UNBOUNDED FOLLOWING 47 | ) AS Last_City 48 | FROM Hosts 49 | ORDER BY Year ASC; 50 | 51 | -- Ranking athletes by medals earned 52 | WITH Athlete_Medals AS ( 53 | SELECT 54 | Athlete, 55 | COUNT(*) AS Medals 56 | FROM Summer_Medals 57 | GROUP BY Athlete) 58 | 59 | SELECT 60 | Athlete, 61 | Medals, 62 | RANK() OVER (ORDER BY Medals DESC) AS Rank_N 63 | FROM Athlete_Medals 64 | ORDER BY Medals DESC; 65 | 66 | -- Ranking athletes from multiple countries 67 | WITH Athlete_Medals AS ( 68 | SELECT 69 | Country, Athlete, COUNT(*) AS Medals 70 | FROM Summer_Medals 71 | WHERE 72 | Country IN ('JPN', 'KOR') 73 | AND Year >= 2000 74 | GROUP BY Country, Athlete 75 | HAVING COUNT(*) > 1) 76 | 77 | SELECT 78 | Country, 79 | Athlete, 80 | DENSE_RANK() OVER (PARTITION BY Country 81 | ORDER BY Medals DESC) AS Rank_N 82 | FROM Athlete_Medals 83 | ORDER BY Country ASC, RANK_N ASC; 84 | 85 | /* 86 | Q: DENSE_RANK's output 87 | 88 | You have the following table: 89 | 90 | | Country | Medals | 91 | |---------|--------| 92 | | IRN | 23 | 93 | | IRQ | 19 | 94 | | LBN | 19 | 95 | | SYR | 19 | 96 | | BHR | 7 | 97 | | KSA | 3 | 98 | 99 | If you were to use DENSE_RANK to order the Medals column in descending order, what rank would BHR be assigned? 100 | 101 | ANS: 3 102 | */ 103 | 104 | -- Paging events 105 | WITH Events AS ( 106 | SELECT DISTINCT Event 107 | FROM Summer_Medals) 108 | 109 | SELECT 110 | Event, 111 | NTILE(111) OVER (ORDER BY Event ASC) AS Page 112 | FROM Events 113 | ORDER BY Event ASC; 114 | 115 | -- Top, middle, and bottom thirds 116 | -- (1) 117 | WITH Athlete_Medals AS ( 118 | SELECT Athlete, COUNT(*) AS Medals 119 | FROM Summer_Medals 120 | GROUP BY Athlete 121 | HAVING COUNT(*) > 1) 122 | 123 | SELECT 124 | Athlete, 125 | Medals, 126 | NTILE(3) OVER (ORDER BY Medals DESC) AS Third 127 | FROM Athlete_Medals 128 | ORDER BY Medals DESC, Athlete ASC; 129 | 130 | -- (2) 131 | WITH Athlete_Medals AS ( 132 | SELECT Athlete, COUNT(*) AS Medals 133 | FROM Summer_Medals 134 | GROUP BY Athlete 135 | HAVING COUNT(*) > 1), 136 | 137 | Thirds AS ( 138 | SELECT 139 | Athlete, 140 | Medals, 141 | NTILE(3) OVER (ORDER BY Medals DESC) AS Third 142 | FROM Athlete_Medals) 143 | 144 | SELECT 145 | Third, 146 | AVG(Medals) AS Avg_Medals 147 | FROM Thirds 148 | GROUP BY Third 149 | ORDER BY Third ASC; -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/DATASET/postgres-sakila-incremental-schema_06172019.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE mpaa_rating AS ENUM ( 2 | 'G', 3 | 'PG', 4 | 'PG-13', 5 | 'R', 6 | 'NC-17' 7 | ); 8 | 9 | 10 | ALTER TABLE film 11 | ALTER COLUMN rating TYPE mpaa_rating USING rating::mpaa_rating, 12 | ALTER COLUMN rating SET DEFAULT 'G'::mpaa_rating; 13 | 14 | CREATE OR REPLACE FUNCTION get_customer_balance(p_customer_id integer, p_effective_date timestamp with time zone) RETURNS numeric 15 | LANGUAGE plpgsql 16 | AS $$ 17 | --#OK, WE NEED TO CALCULATE THE CURRENT BALANCE GIVEN A CUSTOMER_ID AND A DATE 18 | --#THAT WE WANT THE BALANCE TO BE EFFECTIVE FOR. THE BALANCE IS: 19 | --# 1) RENTAL FEES FOR ALL PREVIOUS RENTALS 20 | --# 2) ONE DOLLAR FOR EVERY DAY THE PREVIOUS RENTALS ARE OVERDUE 21 | --# 3) IF A FILM IS MORE THAN RENTAL_DURATION * 2 OVERDUE, CHARGE THE REPLACEMENT_COST 22 | --# 4) SUBTRACT ALL PAYMENTS MADE BEFORE THE DATE SPECIFIED 23 | DECLARE 24 | v_rentfees DECIMAL(5,2); --#FEES PAID TO RENT THE VIDEOS INITIALLY 25 | v_overfees INTEGER; --#LATE FEES FOR PRIOR RENTALS 26 | v_payments DECIMAL(5,2); --#SUM OF PAYMENTS MADE PREVIOUSLY 27 | BEGIN 28 | SELECT COALESCE(SUM(film.rental_rate),0) INTO v_rentfees 29 | FROM film, inventory, rental 30 | WHERE film.film_id = inventory.film_id 31 | AND inventory.inventory_id = rental.inventory_id 32 | AND rental.rental_date <= p_effective_date 33 | AND rental.customer_id = p_customer_id; 34 | 35 | SELECT COALESCE(SUM(IF((rental.return_date - rental.rental_date) > (film.rental_duration * '1 day'::interval), 36 | ((rental.return_date - rental.rental_date) - (film.rental_duration * '1 day'::interval)),0)),0) INTO v_overfees 37 | FROM rental, inventory, film 38 | WHERE film.film_id = inventory.film_id 39 | AND inventory.inventory_id = rental.inventory_id 40 | AND rental.rental_date <= p_effective_date 41 | AND rental.customer_id = p_customer_id; 42 | 43 | SELECT COALESCE(SUM(payment.amount),0) INTO v_payments 44 | FROM payment 45 | WHERE payment.payment_date <= p_effective_date 46 | AND payment.customer_id = p_customer_id; 47 | 48 | RETURN v_rentfees + v_overfees - v_payments; 49 | END 50 | $$; 51 | 52 | CREATE OR REPLACE FUNCTION inventory_held_by_customer(p_inventory_id integer) RETURNS integer 53 | LANGUAGE plpgsql 54 | AS $$ 55 | DECLARE 56 | v_customer_id INTEGER; 57 | BEGIN 58 | 59 | SELECT customer_id INTO v_customer_id 60 | FROM rental 61 | WHERE return_date IS NULL 62 | AND inventory_id = p_inventory_id; 63 | 64 | RETURN v_customer_id; 65 | END $$; 66 | 67 | CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean 68 | LANGUAGE plpgsql 69 | AS $$ 70 | DECLARE 71 | v_rentals INTEGER; 72 | v_out INTEGER; 73 | BEGIN 74 | -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE 75 | -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED 76 | 77 | SELECT count(*) INTO v_rentals 78 | FROM rental 79 | WHERE inventory_id = p_inventory_id; 80 | 81 | IF v_rentals = 0 THEN 82 | RETURN TRUE; 83 | END IF; 84 | 85 | SELECT COUNT(rental_id) INTO v_out 86 | FROM inventory LEFT JOIN rental USING(inventory_id) 87 | WHERE inventory.inventory_id = p_inventory_id 88 | AND rental.return_date IS NULL; 89 | 90 | IF v_out > 0 THEN 91 | RETURN FALSE; 92 | ELSE 93 | RETURN TRUE; 94 | END IF; 95 | END $$; 96 | -------------------------------------------------------------------------------- /PostgreSQL Summary Stats and Window Functions /1.Introduction To Window Functions.sql: -------------------------------------------------------------------------------- 1 | -- Which of the following is FALSE? 2 | -- Ans:Window functions can open a "window" to another table, whereas GROUP BY functions cannot. 3 | 4 | -- Numbering rows 5 | SELECT 6 | *, 7 | ROW_NUMBER() OVER() AS Row_N 8 | FROM Summer_Medals 9 | ORDER BY Row_N ASC; 10 | 11 | -- Numbering Olympic games in ascending order 12 | SELECT 13 | Year, 14 | ROW_NUMBER() OVER() AS Row_N 15 | FROM ( 16 | SELECT DISTINCT year 17 | FROM Summer_Medals 18 | ORDER BY Year ASC 19 | ) AS Years 20 | ORDER BY Year ASC; 21 | 22 | -- Numbering Olympic games in descending order 23 | SELECT 24 | Year, 25 | ROW_NUMBER() OVER (ORDER BY Year DESC) AS Row_N 26 | FROM ( 27 | SELECT DISTINCT Year 28 | FROM Summer_Medals 29 | ) AS Years 30 | ORDER BY Year; 31 | 32 | -- Numbering Olympic athletes by medals earned 33 | -- (1) 34 | SELECT 35 | athlete, 36 | COUNT(sport) AS Medals 37 | FROM Summer_Medals 38 | GROUP BY Athlete 39 | ORDER BY Medals DESC; 40 | 41 | -- (2) 42 | WITH Athlete_Medals AS ( 43 | SELECT 44 | Athlete, 45 | COUNT(*) AS Medals 46 | FROM Summer_Medals 47 | GROUP BY Athlete) 48 | 49 | SELECT 50 | Athlete, 51 | ROW_NUMBER() OVER (ORDER BY Medals DESC) AS Row_N 52 | FROM Athlete_Medals 53 | ORDER BY Medals DESC; 54 | 55 | -- Reigning weightlifting champions 56 | -- (1) 57 | SELECT 58 | Year, 59 | Country AS champion 60 | FROM Summer_Medals 61 | WHERE 62 | Discipline = 'Weightlifting' AND 63 | Event = '69KG' AND 64 | Gender = 'Men' AND 65 | Medal = 'Gold'; 66 | 67 | -- (2) 68 | WITH Weightlifting_Gold AS ( 69 | SELECT 70 | Year, 71 | Country AS champion 72 | FROM Summer_Medals 73 | WHERE 74 | Discipline = 'Weightlifting' AND 75 | Event = '69KG' AND 76 | Gender = 'Men' AND 77 | Medal = 'Gold') 78 | 79 | SELECT 80 | Year, Champion, 81 | LAG(Champion) OVER 82 | (ORDER BY Weightlifting_Gold ASC) AS Last_Champion 83 | FROM Weightlifting_Gold 84 | ORDER BY Year ASC; 85 | 86 | -- Reigning champions by gender 87 | WITH Tennis_Gold AS ( 88 | SELECT DISTINCT 89 | Gender, Year, Country 90 | FROM Summer_Medals 91 | WHERE 92 | Year >= 2000 AND 93 | Event = 'Javelin Throw' AND 94 | Medal = 'Gold') 95 | 96 | SELECT 97 | Gender, Year, 98 | Country AS Champion, 99 | LAG(Country) OVER (PARTITION BY Gender 100 | ORDER BY Year ASC) AS Last_Champion 101 | FROM Tennis_Gold 102 | ORDER BY Gender ASC, Year ASC; 103 | 104 | -- Reigning champions by gender and event 105 | WITH Athletics_Gold AS ( 106 | SELECT DISTINCT 107 | Gender, Year, Event, Country 108 | FROM Summer_Medals 109 | WHERE 110 | Year >= 2000 AND 111 | Discipline = 'Athletics' AND 112 | Event IN ('100M', '10000M') AND 113 | Medal = 'Gold') 114 | 115 | SELECT 116 | Gender, Year, Event, 117 | Country AS Champion, 118 | LAG(Country) OVER (PARTITION BY Gender, Event 119 | ORDER BY Year ASC) AS Last_Champion 120 | FROM Athletics_Gold 121 | ORDER BY Event ASC, Gender ASC, Year ASC; 122 | 123 | 124 | /* 125 | -- Row numbers with partitioning 126 | 127 | If you run ROW_NUMBER() OVER (PARTITION BY Year ORDER BY Medals DESC) on the following table, what row number would the 2008 Iranian record have? 128 | 129 | | Year | Country | Medals | 130 | |------|---------|--------| 131 | | 2004 | IRN | 32 | 132 | | 2004 | LBN | 17 | 133 | | 2004 | KSA | 4 | 134 | | 2008 | IRQ | 29 | 135 | | 2008 | IRN | 27 | 136 | | 2008 | UAE | 12 | 137 | 138 | -- Ans: 2 139 | */ -------------------------------------------------------------------------------- /PostgreSQL Summary Stats and Window Functions /3.Aggregate window functions and frames.sql: -------------------------------------------------------------------------------- 1 | -- Running totals of athlete medals 2 | WITH Athlete_Medals AS ( 3 | SELECT 4 | Athlete, COUNT(*) AS Medals 5 | FROM Summer_Medals 6 | WHERE 7 | Country = 'USA' AND Medal = 'Gold' 8 | AND Year >= 2000 9 | GROUP BY Athlete) 10 | 11 | SELECT 12 | Athlete, 13 | Medals, 14 | SUM(Medals) OVER (ORDER BY Athlete ASC) AS Max_Medals 15 | FROM Athlete_Medals 16 | ORDER BY Athlete ASC; 17 | 18 | -- Maximum country medals by year 19 | 20 | WITH Country_Medals AS ( 21 | SELECT 22 | Year, Country, COUNT(*) AS Medals 23 | FROM Summer_Medals 24 | WHERE 25 | Country IN ('CHN', 'KOR', 'JPN') 26 | AND Medal = 'Gold' AND Year >= 2000 27 | GROUP BY Year, Country) 28 | 29 | SELECT 30 | Year, 31 | Country, 32 | Medals, 33 | MAX(Medals) OVER (PARTITION BY Country ORDER BY Year ASC) AS Max_Medals 34 | FROM Country_Medals 35 | ORDER BY Country ASC, Year ASC; 36 | 37 | -- Minimum country medals by year 38 | WITH France_Medals AS ( 39 | SELECT 40 | Year, COUNT(*) AS Medals 41 | FROM Summer_Medals 42 | WHERE 43 | Country = 'FRA' 44 | AND Medal = 'Gold' AND Year >= 2000 45 | GROUP BY Year) 46 | 47 | SELECT 48 | Year, 49 | Medals, 50 | MIN(Medals) OVER (ORDER BY Year ASC) AS Min_Medals 51 | FROM France_Medals 52 | ORDER BY Year ASC; 53 | 54 | /* 55 | -- Number of rows in a frame 56 | Q: How many rows does the following frame span? 57 | ROWS BETWEEN 3 PRECEDING AND 2 FOLLOWING 58 | A: 6 59 | */ 60 | 61 | -- Moving maximum of Scandinavian athletes' medals 62 | WITH Scandinavian_Medals AS ( 63 | SELECT 64 | Year, COUNT(*) AS Medals 65 | FROM Summer_Medals 66 | WHERE 67 | Country IN ('DEN', 'NOR', 'FIN', 'SWE', 'ISL') 68 | AND Medal = 'Gold' 69 | GROUP BY Year) 70 | 71 | SELECT 72 | Year, 73 | Medals, 74 | MAX(Medals) OVER (ORDER BY YEAR ASC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING ) AS Max_Medals 75 | FROM Scandinavian_Medals 76 | ORDER BY Year ASC; 77 | 78 | -- Moving maximum of Chinese athletes' medals 79 | WITH Chinese_Medals AS ( 80 | SELECT 81 | Athlete, COUNT(*) AS Medals 82 | FROM Summer_Medals 83 | WHERE 84 | Country = 'CHN' AND Medal = 'Gold' 85 | AND Year >= 2000 86 | GROUP BY Athlete) 87 | 88 | SELECT 89 | Athlete, 90 | Medals, 91 | MAX(Medals) OVER (ORDER BY Athlete ASC ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS Max_Medals 92 | FROM Chinese_Medals 93 | ORDER BY Athlete ASC; 94 | 95 | /* 96 | -- Moving average's frame 97 | Q: If you want your moving average to cover the last 3 and current Olympic games, how would you define its frame? 98 | A: ROWS BETWEEN 3 PRECEDING AND CURRENT ROW 99 | */ 100 | 101 | -- Moving average of Russian medals 102 | WITH Russian_Medals AS ( 103 | SELECT 104 | Year, COUNT(*) AS Medals 105 | FROM Summer_Medals 106 | WHERE 107 | Country = 'RUS' 108 | AND Medal = 'Gold' 109 | AND Year >= 1980 110 | GROUP BY Year) 111 | 112 | SELECT 113 | Year, Medals, 114 | AVG(Medals) OVER 115 | (ORDER BY Year ASC ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS Medals_MA 116 | FROM Russian_Medals 117 | ORDER BY Year ASC; 118 | 119 | -- Moving total of countries' medals 120 | WITH Country_Medals AS ( 121 | SELECT 122 | Year, Country, COUNT(*) AS Medals 123 | FROM Summer_Medals 124 | GROUP BY Year, Country) 125 | 126 | SELECT 127 | Year, Country, Medals, 128 | SUM(Medals) OVER 129 | (PARTITION BY Country 130 | ORDER BY Year ASC 131 | ROWS BETWEEN 132 | 2 PRECEDING AND CURRENT ROW) AS Medals_MA 133 | FROM Country_Medals 134 | ORDER BY Country ASC, Year ASC; -------------------------------------------------------------------------------- /Joining Data in SQL/4) Subqueries.sql: -------------------------------------------------------------------------------- 1 | -- Subquery inside where 2 | -- (1) 3 | 4 | SELECT AVG(life_expectancy) 5 | FROM populations 6 | WHERE Year=2015; 7 | 8 | -- (2) 9 | 10 | SELECT * 11 | FROM populations 12 | WHERE life_expectancy > 1.15 * 13 | (SELECT AVG(life_expectancy) 14 | FROM populations 15 | WHERE year = 2015) 16 | AND year = 2015; 17 | 18 | -- Subquery inside where (2) 19 | 20 | SELECT cities.name, country_code, urbanarea_pop 21 | FROM cities 22 | WHERE cities.name IN 23 | (SELECT capital 24 | FRoM countries) 25 | ORDER BY urbanarea_pop DESC; 26 | 27 | -- Subquery inside select 28 | 29 | SELECT countries.name AS country, 30 | (SELECT COUNT(*) 31 | FROM cities 32 | WHERE countries.code = cities.country_code) AS cities_num 33 | FROM countries 34 | ORDER BY cities_num DESC, country 35 | LIMIT 9; 36 | 37 | -- Subquery inside from 38 | -- (1) 39 | SELECT code, COUNT(name) AS lang_num 40 | FROM languages 41 | GROUP BY code; 42 | 43 | -- (2) 44 | 45 | SELECT local_name, subquery.lang_num 46 | FROM countries, 47 | (SELECT code, COUNT(name) AS lang_num 48 | FROM languages 49 | GROUP BY code) AS subquery 50 | WHERE countries.code = subquery.code 51 | ORDER BY lang_num DESC; 52 | 53 | -- Advanced subquery 54 | 55 | -- (1) 56 | 57 | SELECT name, continent, inflation_rate 58 | FROM countries 59 | INNER JOIN economies 60 | USING (code) 61 | WHERE year = 2015; 62 | 63 | -- (2) 64 | 65 | SELECT MAX(inflation_rate) AS max_inf 66 | FROM ( 67 | SELECT name, continent, inflation_rate 68 | FROM countries 69 | INNER JOIN economies 70 | USING (code) 71 | WHERE year = 2015) AS subquery 72 | GROUP BY continent; 73 | 74 | -- (3) 75 | 76 | SELECT name, continent, inflation_rate 77 | FROM countries 78 | INNER JOIN economies 79 | ON countries.code = economies.code 80 | WHERE year = 2015 81 | AND inflation_rate IN ( 82 | SELECT MAX(inflation_rate) AS max_inf 83 | FROM ( 84 | SELECT name, continent, inflation_rate 85 | FROM countries 86 | INNER JOIN economies 87 | ON countries.code = economies.code 88 | WHERE year = 2015) AS subquery 89 | GROUP BY continent); 90 | 91 | -- Subquery challenge 92 | 93 | SELECT code, inflation_rate, unemployment_rate 94 | FROM economies 95 | WHERE year = 2015 AND code NOT IN 96 | (SELECT code 97 | FROM countries 98 | WHERE (gov_form = 'Constitutional Monarchy' OR gov_form LIKE '%Republic')) 99 | ORDER BY inflation_rate; 100 | 101 | -- Subquery review 102 | -- Ans:- WHERE 103 | 104 | -- Final challenge 105 | 106 | SELECT DISTINCT c.name, e.total_investment, e.imports 107 | FROM countries AS c 108 | LEFT JOIN economies AS e 109 | ON (c.code = e.code AND c.code IN 110 | (SELECT code 111 | FROM languages 112 | WHERE official = 'true')) 113 | WHERE year = 2015 AND region = 'Central America' 114 | ORDER BY c.name; 115 | 116 | -- Final challenge (2) 117 | 118 | SELECT region, continent, AVG(fertility_rate) AS avg_fert_rate 119 | FROM countries AS c 120 | INNER JOIN populations AS p 121 | ON c.code = p.country_code 122 | WHERE year = 2015 123 | GROUP BY region, continent 124 | ORDER BY avg_fert_rate; 125 | 126 | -- Final challenge (3) 127 | 128 | SELECT name, country_code, city_proper_pop, metroarea_pop, 129 | city_proper_pop / metroarea_pop * 100 AS city_perc 130 | FROM cities 131 | WHERE name IN 132 | (SELECT capital 133 | FROM countries 134 | WHERE (continent = 'Europe' 135 | OR continent LIKE '%America')) 136 | AND metroarea_pop IS NOT NULL 137 | ORDER BY city_perc DESC 138 | LIMIT 10; 139 | 140 | -------------------------------------------------------------------------------- /Intermediate SQL/2. Short and Simple Subqueries.sql: -------------------------------------------------------------------------------- 1 | -- Filtering using scalar subqueries 2 | 3 | -- (1) 4 | SELECT 5 | 3 * AVG(home_goal + away_goal) 6 | FROM matches_2013_2014; 7 | 8 | -- (2) 9 | SELECT 10 | date, 11 | home_goal, 12 | away_goal 13 | FROM matches_2013_2014 14 | WHERE (home_goal + away_goal) > 15 | (SELECT 3 * AVG(home_goal + away_goal) 16 | FROM matches_2013_2014); 17 | 18 | -- Filtering using a subquery with a list 19 | SELECT 20 | team_long_name, 21 | team_short_name 22 | FROM team 23 | WHERE team_api_id NOT IN 24 | (SELECT DISTINCT hometeam_ID FROM match); 25 | 26 | -- Filtering with more complex subquery conditions 27 | SELECT 28 | team_long_name, 29 | team_short_name 30 | FROM team 31 | WHERE team_api_id IN 32 | (SELECT hometeam_id 33 | FROM match 34 | WHERE home_goal >= 8); 35 | 36 | -- Joining Subqueries in FROM 37 | 38 | -- (1) 39 | SELECT 40 | country_id, 41 | id 42 | FROM match 43 | WHERE (home_goal + away_goal) >= 10; 44 | 45 | -- (2) 46 | SELECT 47 | c.name AS country_name, 48 | COUNT(sub.id) AS matches 49 | FROM country AS c 50 | INNER JOIN (SELECT country_id, id 51 | FROM match 52 | WHERE (home_goal + away_goal) >= 10 ) AS sub 53 | ON c.id = sub.country_id 54 | GROUP BY country_name; 55 | 56 | -- Building on Subqueries in FROM 57 | SELECT 58 | country, 59 | date, 60 | home_goal, 61 | away_goal 62 | FROM 63 | (SELECT c.name AS country, 64 | m.date, 65 | m.home_goal, 66 | m.away_goal, 67 | ( m.home_goal + m.away_goal) AS total_goals 68 | FROM match AS m 69 | LEFT JOIN country AS c 70 | ON m.country_id = c.id) AS subq 71 | WHERE total_goals >= 10; 72 | 73 | -- Add a subquery to the SELECT clause 74 | SELECT 75 | l.name AS league, 76 | ROUND(AVG(m.home_goal + m.away_goal), 2) AS avg_goals, 77 | (SELECT ROUND(AVG(home_goal + away_goal), 2) 78 | FROM match 79 | WHERE season = '2013/2014') AS overall_avg 80 | FROM league AS l 81 | LEFT JOIN match AS m 82 | ON l.country_id = m.country_id 83 | WHERE m.season = '2013/2014' 84 | GROUP BY l.name; 85 | 86 | -- Subqueries in Select for Calculations 87 | SELECT 88 | l.name AS league, 89 | ROUND(AVG(m.home_goal + m.away_goal),2) AS avg_goals, 90 | ROUND(AVG(m.home_goal + m.away_goal) - 91 | (SELECT AVG(home_goal + away_goal) 92 | FROM match 93 | WHERE season = '2013/2014'),2) AS diff 94 | FROM league AS l 95 | LEFT JOIN match AS m 96 | ON l.country_id = m.country_id 97 | WHERE m.season = '2013/2014' 98 | GROUP BY l.name; 99 | 100 | -- ALL the Subqueries EVERYWHERE 101 | SELECT 102 | m.stage, 103 | ROUND(AVG(m.home_goal + m.away_goal),2) AS avg_goals, 104 | ROUND((SELECT AVG(home_goal + away_goal) 105 | FROM match 106 | WHERE season = '2012/2013'),2) AS overall 107 | FROM match AS m 108 | WHERE m.season = '2012/2013' 109 | GROUP BY m.stage; 110 | 111 | -- Add a subquery in FROM 112 | SELECT 113 | s.stage, 114 | ROUND(s.avg_goals,2) AS avg_goals 115 | FROM 116 | (SELECT 117 | stage, 118 | AVG(home_goal + away_goal) AS avg_goals 119 | FROM match 120 | WHERE season = '2012/2013' 121 | GROUP BY stage) AS s 122 | WHERE 123 | s.avg_goals > (SELECT AVG(home_goal + away_goal) 124 | FROM match WHERE season = '2012/2013'); 125 | 126 | -- Add a subquery in SELECT 127 | SELECT 128 | s.stage, 129 | ROUND(s.avg_goals,2) AS avg_goal, 130 | (SELECT AVG(home_goal + away_goal) FROM match WHERE season = '2012/2013') AS overall_avg 131 | FROM 132 | (SELECT 133 | stage, 134 | AVG(home_goal + away_goal) AS avg_goals 135 | FROM match 136 | WHERE season = '2012/2013' 137 | GROUP BY stage) AS s 138 | WHERE 139 | s.avg_goals > (SELECT AVG(home_goal + away_goal) 140 | FROM match WHERE season = '2012/2013'); -------------------------------------------------------------------------------- /PostgreSQL Summary Stats and Window Functions /4.Beyond Window Functions.sql: -------------------------------------------------------------------------------- 1 | -- A basic pivot 2 | CREATE EXTENSION IF NOT EXISTS tablefunc; 3 | 4 | SELECT * FROM CROSSTAB($$ 5 | SELECT 6 | Gender, Year, Country 7 | FROM Summer_Medals 8 | WHERE 9 | Year IN (2008, 2012) 10 | AND Medal = 'Gold' 11 | AND Event = 'Pole Vault' 12 | ORDER By Gender ASC, Year ASC; 13 | $$) AS ct (Gender VARCHAR, 14 | Year VARCHAR, 15 | Country VARCHAR) 16 | 17 | ORDER BY Gender ASC; 18 | 19 | -- Pivoting with ranking 20 | -- (1) 21 | SELECT 22 | Country, 23 | Year, 24 | COUNT(*) AS Awards 25 | FROM Summer_Medals 26 | WHERE 27 | Country IN ('FRA', 'GBR', 'GER') 28 | AND Year IN (2004, 2008, 2012) 29 | AND Medal = 'Gold' 30 | GROUP BY Country, Year 31 | ORDER BY Country ASC, Year ASC 32 | 33 | -- (2) 34 | WITH Country_Awards AS ( 35 | SELECT 36 | Country, 37 | Year, 38 | COUNT(*) AS Awards 39 | FROM Summer_Medals 40 | WHERE 41 | Country IN ('FRA', 'GBR', 'GER') 42 | AND Year IN (2004, 2008, 2012) 43 | AND Medal = 'Gold' 44 | GROUP BY Country, Year) 45 | 46 | SELECT 47 | Country, 48 | Year, 49 | RANK() OVER(PARTITION BY Year ORDER BY Awards) :: INTEGER AS rank 50 | FROM Country_Awards 51 | ORDER BY Country ASC, Year ASC; 52 | 53 | -- (3) 54 | CREATE EXTENSION IF NOT EXISTS tablefunc; 55 | 56 | SELECT * FROM CROSSTAB($$ 57 | WITH Country_Awards AS ( 58 | SELECT 59 | Country, 60 | Year, 61 | COUNT(*) AS Awards 62 | FROM Summer_Medals 63 | WHERE 64 | Country IN ('FRA', 'GBR', 'GER') 65 | AND Year IN (2004, 2008, 2012) 66 | AND Medal = 'Gold' 67 | GROUP BY Country, Year) 68 | 69 | SELECT 70 | Country, 71 | Year, 72 | RANK() OVER 73 | (PARTITION BY Year 74 | ORDER BY Awards DESC) :: INTEGER AS rank 75 | FROM Country_Awards 76 | ORDER BY Country ASC, Year ASC; 77 | $$) AS ct (Country VARCHAR, 78 | "2004" INTEGER, 79 | "2008" INTEGER, 80 | "2012" INTEGER) 81 | 82 | Order by Country ASC; 83 | 84 | -- Country-level subtotals 85 | SELECT 86 | Country, 87 | Gender, 88 | COUNT(*) AS Gold_Awards 89 | FROM Summer_Medals 90 | WHERE 91 | Year = 2004 92 | AND Medal = 'Gold' 93 | AND Country IN ('DEN', 'NOR', 'SWE') 94 | GROUP BY Country, ROLLUP(Gender) 95 | ORDER BY Country ASC, Gender ASC; 96 | 97 | -- All group-level subtotals 98 | SELECT 99 | Gender, 100 | Medal, 101 | COUNT(*) AS Awards 102 | FROM Summer_Medals 103 | WHERE 104 | Year = 2012 105 | AND Country = 'RUS' 106 | GROUP BY CUBE(Gender, Medal) 107 | ORDER BY Gender ASC, Medal ASC; 108 | 109 | -- Cleaning up results 110 | SELECT 111 | COALESCE(Country, 'All countries') AS Country, 112 | COALESCE(Gender, 'All genders') AS Gender, 113 | COUNT(*) AS Awards 114 | FROM Summer_Medals 115 | WHERE 116 | Year = 2004 117 | AND Medal = 'Gold' 118 | AND Country IN ('DEN', 'NOR', 'SWE') 119 | GROUP BY ROLLUP(Country, Gender) 120 | ORDER BY Country ASC, Gender ASC; 121 | 122 | -- Summarizing results 123 | -- (1) 124 | WITH Country_Medals AS ( 125 | SELECT 126 | Country, 127 | COUNT(*) AS Medals 128 | FROM Summer_Medals 129 | WHERE Year = 2000 130 | AND Medal = 'Gold' 131 | GROUP BY Country) 132 | 133 | SELECT 134 | Country, 135 | RANK() OVER(ORDER BY Medals DESC) AS Rank 136 | FROM Country_Medals 137 | ORDER BY Rank ASC; 138 | 139 | -- (2) 140 | WITH Country_Medals AS ( 141 | SELECT 142 | Country, 143 | COUNT(*) AS Medals 144 | FROM Summer_Medals 145 | WHERE Year = 2000 146 | AND Medal = 'Gold' 147 | GROUP BY Country), 148 | 149 | Country_Ranks AS ( 150 | SELECT 151 | Country, 152 | RANK() OVER (ORDER BY Medals DESC) AS Rank 153 | FROM Country_Medals 154 | ORDER BY Rank ASC) 155 | 156 | SELECT STRING_AGG(Country,', ') 157 | FROM Country_Ranks 158 | -- Select only the top three ranks 159 | WHERE RANK <= 3; -------------------------------------------------------------------------------- /Functions for Manipulating Data in PostgreSQL/2.Working with DATE-TIME Functions and Operators.sql: -------------------------------------------------------------------------------- 1 | -- Adding and subtracting date and time values 2 | -- (1) 3 | SELECT f.title, f.rental_duration, 4 | r.return_date - r.rental_date AS days_rented 5 | FROM film AS f 6 | INNER JOIN inventory AS i ON f.film_id = i.film_id 7 | INNER JOIN rental AS r ON i.inventory_id = r.inventory_id 8 | ORDER BY f.title; 9 | 10 | -- (2) 11 | SELECT f.title, f.rental_duration, 12 | AGE(r.return_date, r.rental_date) AS days_rented 13 | FROM film AS f 14 | INNER JOIN inventory AS i ON f.film_id = i.film_id 15 | INNER JOIN rental AS r ON i.inventory_id = r.inventory_id 16 | WHERE r.return_date IS NOT NULL 17 | ORDER BY f.title; 18 | 19 | -- INTERVAL arithmetic 20 | SELECT 21 | f.title, 22 | INTERVAL '1' day * f.rental_duration, 23 | r.return_date - r.rental_date AS days_rented 24 | FROM film AS f 25 | INNER JOIN inventory AS i ON f.film_id = i.film_id 26 | INNER JOIN rental AS r ON i.inventory_id = r.inventory_id 27 | WHERE r.return_date IS NOT NULL 28 | ORDER BY f.title; 29 | 30 | -- Calculating the expected return date 31 | SELECT 32 | f.title, 33 | r.rental_date, 34 | f.rental_duration, 35 | INTERVAL '1' day * f.rental_duration + r.rental_date AS expected_return_date, 36 | r.return_date 37 | FROM film AS f 38 | INNER JOIN inventory AS i ON f.film_id = i.film_id 39 | INNER JOIN rental AS r ON i.inventory_id = r.inventory_id 40 | ORDER BY f.title; 41 | 42 | -- Working with the current date and time 43 | -- (1) 44 | SELECT NOW(); 45 | 46 | -- (2) 47 | SELECT CURRENT_DATE; 48 | 49 | -- (3) 50 | SELECT CAST( NOW() AS timestamp ) 51 | 52 | -- (4) 53 | SELECT 54 | CURRENT_DATE, 55 | CAST( NOW() AS date ) 56 | 57 | -- Manipulating the current date and time 58 | -- (1) 59 | SELECT 60 | CURRENT_TIMESTAMP::timestamp AS right_now; 61 | 62 | -- (2) 63 | SELECT 64 | CURRENT_TIMESTAMP::timestamp AS right_now, 65 | INTERVAL '5 ___' + CURRENT_TIMESTAMP AS five_days_from_now; 66 | 67 | -- (3) 68 | SELECT 69 | CURRENT_TIMESTAMP(0)::timestamp AS right_now, 70 | interval '5 days' + CURRENT_TIMESTAMP(0) AS five_days_from_now; 71 | 72 | -- Using EXTRACT 73 | -- (1) 74 | SELECT 75 | EXTRACT(dow FROM rental_date) AS dayofweek 76 | FROM rental 77 | LIMIT 100; 78 | 79 | -- (2) 80 | SELECT 81 | EXTRACT(dow FROM rental_date) AS dayofweek, 82 | COUNT(rental_id) as rentals 83 | FROM rental 84 | GROUP BY 1; 85 | 86 | -- Using DATE_TRUNC 87 | -- (1) 88 | SELECT DATE_TRUNC('Year', rental_date) AS rental_year 89 | FROM rental; 90 | 91 | -- (2) 92 | SELECT DATE_TRUNC('Month', rental_date) AS rental_month 93 | FROM rental; 94 | 95 | -- (3) 96 | SELECT DATE_TRUNC('Day', rental_date) AS rental_day 97 | FROM rental; 98 | 99 | -- (4) 100 | SELECT 101 | DATE_TRUNC('Day', rental_date) AS rental_day, 102 | COUNT(rental_id) AS rentals 103 | FROM rental 104 | GROUP BY 1; 105 | 106 | -- Putting it all together 107 | -- (1) 108 | SELECT 109 | EXTRACT(dow FROM rental_date) AS dayofweek, 110 | AGE(return_date, rental_date) AS rental_days 111 | FROM rental AS r 112 | WHERE 113 | rental_date BETWEEN CAST('2005-05-01' AS DATE) 114 | AND CAST('2005-05-01' AS DATE) + INTERVAL '90 day'; 115 | 116 | -- (2) 117 | SELECT 118 | c.first_name || ' ' || c.last_name AS customer_name, 119 | f.title, 120 | r.rental_date, 121 | EXTRACT(dow FROM r.rental_date) AS dayofweek, 122 | AGE(r.return_date, r.rental_date) AS rental_days, 123 | CASE WHEN DATE_TRUNC('day', AGE(r.return_date, r.rental_date)) > 124 | f.rental_duration * INTERVAL '1' day 125 | THEN TRUE 126 | ELSE FALSE END AS past_due 127 | FROM 128 | film AS f 129 | INNER JOIN inventory AS i 130 | ON f.film_id = i.film_id 131 | INNER JOIN rental AS r 132 | ON i.inventory_id = r.inventory_id 133 | INNER JOIN customer AS c 134 | ON c.customer_id = r.customer_id 135 | WHERE 136 | r.rental_date BETWEEN CAST('2005-05-01' AS DATE) 137 | AND CAST('2005-05-01' AS DATE) + INTERVAL '90 day'; -------------------------------------------------------------------------------- /Intermediate SQL/4. Window Functions.sql: -------------------------------------------------------------------------------- 1 | -- The match is OVER 2 | SELECT 3 | m.id, 4 | c.name AS country, 5 | m.season, 6 | m.home_goal, 7 | m.away_goal, 8 | AVG(m.home_goal + m.away_goal) OVER() AS overall_avg 9 | FROM match AS m 10 | LEFT JOIN country AS c ON m.country_id = c.id; 11 | 12 | 13 | -- What's OVER here? 14 | SELECT 15 | l.name AS league, 16 | AVG(m.home_goal + m.away_goal) AS avg_goals, 17 | RANK() OVER(ORDER BY AVG(m.home_goal + m.away_goal)) AS league_rank 18 | FROM league AS l 19 | LEFT JOIN match AS m 20 | ON l.id = m.country_id 21 | WHERE m.season = '2011/2012' 22 | GROUP BY l.name 23 | ORDER BY league_rank; 24 | 25 | 26 | -- Flip OVER your results 27 | SELECT 28 | l.name AS league, 29 | AVG(m.home_goal + m.away_goal) AS avg_goals, 30 | RANK() OVER(ORDER BY AVG(m.home_goal + m.away_goal) DESC) AS league_rank 31 | FROM league AS l 32 | LEFT JOIN match AS m 33 | ON l.id = m.country_id 34 | WHERE m.season = '2011/2012' 35 | GROUP BY l.name 36 | ORDER BY league_rank; 37 | 38 | 39 | -- PARTITION BY a column 40 | SELECT 41 | date, 42 | season, 43 | home_goal, 44 | away_goal, 45 | CASE WHEN hometeam_id = 8673 THEN 'home' 46 | ELSE 'away' END AS warsaw_location, 47 | AVG(home_goal) OVER(PARTITION BY season) AS season_homeavg, 48 | AVG(away_goal) OVER(PARTITION BY season) AS season_awayavg 49 | FROM match 50 | WHERE 51 | hometeam_id = 8673 52 | OR awayteam_id = 8673 53 | ORDER BY (home_goal + away_goal) DESC; 54 | 55 | 56 | -- PARTITION BY multiple columns 57 | SELECT 58 | date, 59 | season, 60 | home_goal, 61 | away_goal, 62 | CASE WHEN hometeam_id = 8673 THEN 'home' 63 | ELSE 'away' END AS warsaw_location, 64 | AVG(home_goal) OVER(PARTITION BY season, 65 | EXTRACT(month FROM date)) AS season_mo_home, 66 | AVG(away_goal) OVER(PARTITION BY season, 67 | EXTRACT(month FROM date)) AS season_mo_away 68 | FROM match 69 | WHERE 70 | hometeam_id = 8673 71 | OR awayteam_id = 8673 72 | ORDER BY (home_goal + away_goal) DESC; 73 | 74 | 75 | -- Slide to the left 76 | SELECT 77 | date, 78 | home_goal, 79 | away_goal, 80 | SUM(home_goal) OVER(ORDER BY date 81 | ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total, 82 | AVG(home_goal) OVER(ORDER BY date 83 | ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_avg 84 | FROM match 85 | WHERE 86 | hometeam_id = 9908 87 | AND season = '2011/2012'; 88 | 89 | 90 | -- Slide to the right 91 | SELECT 92 | date, 93 | home_goal, 94 | away_goal, 95 | SUM(home_goal) OVER(ORDER BY date DESC 96 | ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS running_total, 97 | AVG(home_goal) OVER(ORDER BY date DESC 98 | ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS running_avg 99 | FROM match 100 | WHERE 101 | awayteam_id = 9908 102 | AND season = '2011/2012'; 103 | 104 | 105 | -- Setting up the home team CTE 106 | SELECT 107 | m.id, 108 | t.team_long_name, 109 | CASE WHEN m.home_goal > m.away_goal THEN 'MU Win' 110 | WHEN m.home_goal < m.away_goal THEN 'MU Loss' 111 | ELSE 'Tie' END AS outcome 112 | FROM match AS m 113 | LEFT JOIN team AS t 114 | ON m.hometeam_id = t.team_api_id 115 | WHERE 116 | m.season = '2014/2015' 117 | AND t.team_long_name = 'Manchester United'; 118 | 119 | 120 | -- Setting up the away team CTE 121 | SELECT 122 | m.id, 123 | t.team_long_name, 124 | CASE WHEN m.home_goal > m.away_goal THEN 'MU Loss' 125 | WHEN m.home_goal < m.away_goal THEN 'MU Win' 126 | ELSE 'Tie' END AS outcome 127 | FROM match AS m 128 | LEFT JOIN team AS t 129 | ON m.awayteam_id = t.team_api_id 130 | WHERE 131 | m.season = '2014/2015' 132 | AND t.team_long_name = 'Manchester United'; 133 | 134 | 135 | -- Putting the CTEs together 136 | WITH home AS ( 137 | SELECT m.id, t.team_long_name, 138 | CASE WHEN m.home_goal > m.away_goal THEN 'MU Win' 139 | WHEN m.home_goal < m.away_goal THEN 'MU Loss' 140 | ELSE 'Tie' END AS outcome 141 | FROM match AS m 142 | LEFT JOIN team AS t ON m.hometeam_id = t.team_api_id), 143 | away AS ( 144 | SELECT m.id, t.team_long_name, 145 | CASE WHEN m.home_goal > m.away_goal THEN 'MU Win' 146 | WHEN m.home_goal < m.away_goal THEN 'MU Loss' 147 | ELSE 'Tie' END AS outcome 148 | FROM match AS m 149 | LEFT JOIN team AS t ON m.awayteam_id = t.team_api_id) 150 | SELECT DISTINCT 151 | m.date, 152 | home.team_long_name AS home_team, 153 | away.team_long_name AS away_team, 154 | m.home_goal, 155 | m.away_goal 156 | FROM match AS m 157 | LEFT JOIN home ON m.id = home.id 158 | LEFT JOIN away ON m.id = away.id 159 | WHERE m.season = '2014/2015' 160 | AND (home.team_long_name = 'Manchester United' 161 | OR away.team_long_name = 'Manchester United'); 162 | 163 | 164 | -- Add a window function 165 | WITH home AS ( 166 | SELECT m.id, t.team_long_name, 167 | CASE WHEN m.home_goal > m.away_goal THEN 'MU Win' 168 | WHEN m.home_goal < m.away_goal THEN 'MU Loss' 169 | ELSE 'Tie' END AS outcome 170 | FROM match AS m 171 | LEFT JOIN team AS t ON m.hometeam_id = t.team_api_id), 172 | away AS ( 173 | SELECT m.id, t.team_long_name, 174 | CASE WHEN m.home_goal > m.away_goal THEN 'MU Loss' 175 | WHEN m.home_goal < m.away_goal THEN 'MU Win' 176 | ELSE 'Tie' END AS outcome 177 | FROM match AS m 178 | LEFT JOIN team AS t ON m.awayteam_id = t.team_api_id) 179 | SELECT DISTINCT 180 | m.date, 181 | home.team_long_name AS home_team, 182 | away.team_long_name AS away_team, 183 | m.home_goal, m.away_goal, 184 | RANK() OVER(ORDER BY ABS(home_goal - away_goal) DESC) as match_rank 185 | FROM match AS m 186 | LEFT JOIN home ON m.id = home.id 187 | LEFT JOIN AWAY ON m.id = away.id 188 | WHERE m.season = '2014/2015' 189 | AND ((home.team_long_name = 'Manchester United' AND home.outcome = 'MU Loss') 190 | OR (away.team_long_name = 'Manchester United' AND away.outcome = 'MU Loss')); -------------------------------------------------------------------------------- /Intermediate SQL/3. Correlated Queries, Nested Queries, and Common Table Expressions.sql: -------------------------------------------------------------------------------- 1 | -- Basic Correlated Subqueries 2 | SELECT 3 | main.country_id, 4 | main.date, 5 | main.home_goal, 6 | main.away_goal 7 | FROM match AS main 8 | WHERE 9 | (home_goal + away_goal) > 10 | (SELECT AVG((sub.home_goal + sub.away_goal) * 3) 11 | FROM match AS sub 12 | -- Join the main query to the subquery in WHERE 13 | WHERE main.country_id = sub.country_id); 14 | 15 | -- Correlated subquery with multiple conditions 16 | SELECT 17 | main.country_id, 18 | main.date, 19 | main.home_goal, 20 | main.away_goal 21 | FROM match AS main 22 | WHERE 23 | (home_goal + away_goal) = 24 | (SELECT MAX(sub.home_goal + sub.away_goal) 25 | FROM match AS sub 26 | WHERE main.country_id = sub.country_id 27 | AND main.season = sub.season); 28 | 29 | -- Nested simple subqueries 30 | SELECT 31 | -- Select the season and max goals scored in a match 32 | season, 33 | MAX(home_goal + away_goal) AS max_goals, 34 | -- Select the overall max goals scored in a match 35 | (SELECT MAX(home_goal + away_goal) FROM match) AS overall_max_goals, 36 | -- Select the max number of goals scored in any match in July 37 | (SELECT MAX(home_goal + away_goal) 38 | FROM match 39 | WHERE id IN ( 40 | SELECT id FROM match WHERE EXTRACT(MONTH FROM date) = 07)) AS july_max_goals 41 | FROM match 42 | GROUP BY season; 43 | 44 | -- Nest a subquery in FROM 45 | 46 | -- (1) 47 | SELECT 48 | country_id, 49 | season, 50 | id 51 | FROM match 52 | WHERE home_goal >= 5 OR away_goal >= 5; 53 | 54 | -- (2) 55 | SELECT 56 | country_id, 57 | season, 58 | COUNT(id) AS matches 59 | FROM ( SELECT 60 | country_id, 61 | season, 62 | id 63 | FROM match 64 | WHERE home_goal >= 5 OR away_goal >= 5) AS subquery 65 | GROUP BY country_id, season; 66 | 67 | -- (3) 68 | SELECT 69 | c.name AS country, 70 | AVG(c.id) AS avg_seasonal_high_scores 71 | FROM country AS c 72 | -- Left join outer_s to country 73 | LEFT JOIN ( 74 | SELECT country_id, season, 75 | COUNT(id) AS matches 76 | FROM ( 77 | SELECT country_id, season, id 78 | FROM match 79 | WHERE home_goal >= 5 OR away_goal >= 5) AS inner_s 80 | GROUP BY country_id, season) AS outer_s 81 | ON c.id = outer_s.country_id 82 | GROUP BY country; 83 | 84 | -- Clean up with CTEs 85 | WITH match_list AS ( 86 | SELECT 87 | country_id, 88 | id 89 | FROM match 90 | WHERE (home_goal + away_goal) >= 10) 91 | SELECT 92 | l.name AS league, 93 | COUNT(match_list.id) AS matches 94 | FROM league AS l 95 | LEFT JOIN match_list ON l.id = match_list.country_id 96 | GROUP BY l.name; 97 | 98 | -- Organizing with CTEs 99 | WITH match_list AS 100 | ( SELECT 101 | l.name AS league, 102 | m.date, 103 | m.home_goal, 104 | m.away_goal, 105 | (m.home_goal + m.away_goal) AS total_goals 106 | FROM match AS m 107 | LEFT JOIN league as l ON m.country_id = l.id) 108 | SELECT league, date, home_goal, away_goal 109 | FROM match_list 110 | WHERE total_goals >= 10; 111 | 112 | -- CTEs with nested subqueries 113 | WITH match_lis t AS ( SELECT 114 | country_id, 115 | (home_goal + away_goal) AS goals 116 | FROM match 117 | WHERE id IN 118 | ( SELECT id 119 | FROM match 120 | WHERE season = '2013/2014' AND EXTRACT(MONTH FROM date) = 08) 121 | ) 122 | SELECT 123 | l.name, 124 | AVG(match_list.goals) 125 | FROM league AS l 126 | LEFT JOIN match_list ON l.id = match_list.country_id 127 | GROUP BY l.name; 128 | 129 | -- Get team names with a subquery 130 | 131 | -- (1) 132 | SELECT 133 | m.id, 134 | t.team_long_name AS hometeam 135 | FROM match AS m 136 | LEFT JOIN team as t 137 | ON m.hometeam_id = team_api_id; 138 | 139 | -- (2) 140 | SELECT 141 | m.date, 142 | hometeam, 143 | awayteam, 144 | m.home_goal, 145 | m.away_goal 146 | FROM match AS m 147 | LEFT JOIN 148 | ( SELECT match.id, team.team_long_name AS hometeam 149 | FROM match 150 | LEFT JOIN team 151 | ON match.hometeam_id = team.team_api_id) AS home 152 | 153 | ON home.id = m.id 154 | LEFT JOIN 155 | ( SELECT match.id, team.team_long_name AS awayteam 156 | FROM match 157 | LEFT JOIN team 158 | -- Get the away team ID in the subquery 159 | ON match.awayteam_id = team.team_api_id) AS away 160 | ON away.id = m.id; 161 | 162 | -- Get team names with correlated subqueries 163 | 164 | -- (1) 165 | SELECT 166 | m.date, 167 | (SELECT team_long_name 168 | FROM team AS t 169 | WHERE t.team_api_id = m.hometeam_id) AS hometeam 170 | FROM match AS m; 171 | 172 | -- (2) 173 | SELECT 174 | m.date, 175 | 176 | (SELECT team_long_name 177 | FROM team AS t 178 | WHERE t.team_api_id = m.hometeam_id) AS hometeam, 179 | 180 | (SELECT team_long_name 181 | FROM team AS t 182 | WHERE t.team_api_id = m.awayteam_id) AS awayteam, 183 | 184 | m.home_goal, 185 | 186 | m.away_goal 187 | 188 | FROM match AS m; 189 | 190 | -- Get team names with CTEs 10 191 | 192 | -- (1) 193 | SELECT 194 | m.id, 195 | t.team_long_name AS hometeam 196 | FROM match AS m 197 | LEFT JOIN team AS t 198 | ON m.hometeam_id = t.team_api_id; 199 | 200 | -- (2) 201 | WITH home AS ( 202 | SELECT m.id, t.team_long_name AS hometeam 203 | FROM match AS m 204 | LEFT JOIN team AS t 205 | ON m.hometeam_id = t.team_api_id) 206 | SELECT * 207 | FROM home; 208 | 209 | -- (3) 210 | WITH home AS 211 | ( SELECT m.id, m.date, 212 | t.team_long_name AS hometeam, m.home_goal 213 | FROM match AS m 214 | LEFT JOIN team AS t 215 | ON m.hometeam_id = t.team_api_id), 216 | away AS ( 217 | SELECT m.id, m.date, 218 | t.team_long_name AS awayteam, m.away_goal 219 | FROM match AS m 220 | LEFT JOIN team AS t 221 | ON m.awayteam_id = t.team_api_id) 222 | SELECT 223 | home.date, 224 | home.hometeam, 225 | away.awayteam, 226 | home.home_goal, 227 | away.away_goal 228 | FROM home 229 | INNER JOIN away 230 | ON home.id = away.id; -------------------------------------------------------------------------------- /Intermediate SQL/1. We'll Take The Case.sql: -------------------------------------------------------------------------------- 1 | -- Basic CASE statements 2 | 3 | -- (1) 4 | SELECT 5 | team_api_id, 6 | team_long_name 7 | FROM teams_germany 8 | WHERE team_long_name IN ( 'FC Schalke 04' , 'FC Bayern Munich'); 9 | 10 | -- (2) 11 | SELECT 12 | CASE WHEN hometeam_id = 10189 THEN 'FC Schalke 04' 13 | WHEN hometeam_id = 9823 THEN 'FC Bayern Munich' 14 | ELSE 'Other' END AS home_team, 15 | COUNT(id) AS total_matches 16 | FROM matches_germany 17 | GROUP BY home_team; 18 | 19 | -- CASE statements comparing column values 20 | 21 | -- (1) 22 | SELECT date, 23 | CASE WHEN home_goal > away_goal THEN 'Home win!' 24 | WHEN home_goal < away_goal THEN 'Home loss :(' 25 | ELSE 'Tie' END AS outcome 26 | FROM matches_spain; 27 | 28 | -- (2) 29 | SELECT 30 | m.date, 31 | t.team_long_name AS opponent, 32 | CASE WHEN m.home_goal > away_goal THEN 'Home win!' 33 | WHEN m.home_goal < away_goal THEN 'Home loss :(' 34 | ELSE 'Tie' END AS outcome 35 | FROM matches_spain AS m 36 | LEFT JOIN teams_spain AS t 37 | ON m.awayteam_id = t.team_api_id; 38 | 39 | -- (3) 40 | SELECT 41 | m.date, 42 | t.team_long_name AS opponent, 43 | CASE WHEN m.home_goal > m.away_goal THEN 'Barcelona win!' 44 | WHEN m.home_goal < m.away_goal THEN 'Barcelona loss :(' 45 | ELSE 'Tie' END AS outcome 46 | FROM matches_spain AS m 47 | LEFT JOIN teams_spain AS t 48 | ON m.awayteam_id = t.team_api_id 49 | WHERE m.hometeam_id = 8634; 50 | 51 | -- CASE statements comparing two column values part 2 52 | SELECT 53 | m.date, 54 | t.team_long_name AS opponent, 55 | CASE WHEN m.home_goal < m.away_goal THEN 'Barcelona win!' 56 | WHEN m.home_goal > m.away_goal THEN 'Barcelona loss :(' 57 | ELSE 'Tie' END AS outcome 58 | FROM matches_spain AS m 59 | LEFT JOIN teams_spain AS t 60 | ON m.hometeam_id = t.team_api_id 61 | WHERE m.awayteam_id = 8634; 62 | 63 | -- In CASE of rivalry 64 | 65 | -- (1) 66 | SELECT 67 | date, 68 | CASE WHEN hometeam_id = 8634 THEN 'FC Barcelona' 69 | ELSE 'Real Madrid CF' END AS home, 70 | CASE WHEN awayteam_id = 8634 THEN 'FC Barcelona' 71 | ELSE 'Real Madrid CF' END AS away 72 | FROM matches_spain 73 | WHERE (awayteam_id = 8634 OR hometeam_id = 8634) 74 | AND (awayteam_id = 8633 OR hometeam_id = 8633); 75 | 76 | -- (2) 77 | SELECT 78 | date, 79 | CASE WHEN hometeam_id = 8634 THEN 'FC Barcelona' 80 | ELSE 'Real Madrid CF' END AS home, 81 | CASE WHEN awayteam_id = 8634 THEN 'FC Barcelona' 82 | ELSE 'Real Madrid CF' END AS away, 83 | CASE WHEN home_goal > away_goal AND hometeam_id = 8634 THEN 'Barcelona win!' 84 | WHEN home_goal > away_goal AND hometeam_id = 8633 THEN 'Real Madrid win!' 85 | WHEN home_goal < away_goal AND awayteam_id = 8634 THEN 'Barcelona win!' 86 | WHEN home_goal < away_goal AND awayteam_id = 8633 THEN 'Real Madrid win!' 87 | ELSE 'Tie!' END AS outcome 88 | FROM matches_spain 89 | WHERE (awayteam_id = 8634 OR hometeam_id = 8634) 90 | AND (awayteam_id = 8633 OR hometeam_id = 8633); 91 | 92 | -- Filtering your CASE statement 93 | 94 | -- (1) 95 | SELECT 96 | team_long_name, 97 | team_api_id 98 | FROM teams_italy 99 | WHERE team_long_name = 'Bologna'; 100 | 101 | -- (2) 102 | SELECT 103 | season, 104 | date, 105 | CASE WHEN hometeam_id = 9857 AND home_goal > away_goal THEN 'Bologna Win' 106 | WHEN awayteam_id = 9857 AND away_goal > home_goal THEN 'Bologna Win' 107 | END AS outcome 108 | FROM matches_italy; 109 | 110 | -- (3) 111 | SELECT 112 | season, 113 | date, 114 | home_goal, 115 | away_goal 116 | FROM matches_italy 117 | WHERE 118 | CASE WHEN hometeam_id = 9857 AND home_goal > away_goal THEN 'Bologna Win' 119 | WHEN awayteam_id = 9857 AND away_goal > home_goal THEN 'Bologna Win' 120 | END IS NOT NULL; 121 | 122 | -- COUNT using CASE WHEN 123 | 124 | -- (1) 125 | SELECT 126 | c.name AS country, 127 | COUNT(CASE WHEN m.season = '2012/2013' 128 | THEN m.id ELSE NULL END) AS matches_2012_2013 129 | FROM country AS c 130 | LEFT JOIN match AS m 131 | ON c.id = m.country_id 132 | GROUP BY c.name; 133 | 134 | -- (2) 135 | SELECT 136 | c.name AS country, 137 | COUNT(CASE WHEN m.season = '2012/2013' THEN m.id END) AS matches_2012_2013, 138 | COUNT(CASE WHEN m.season = '2013/2014' THEN m.id END) AS matches_2013_2014, 139 | COUNT(CASE WHEN m.season = '2014/2015' THEN m.id END) AS matches_2014_2015 140 | FROM country AS c 141 | LEFT JOIN match AS m 142 | ON c.id = m.country_id 143 | GROUP BY c.name; 144 | 145 | -- COUNT and CASE WHEN with multiple conditions 146 | SELECT 147 | c.name AS country, 148 | SUM(CASE WHEN m.season = '2012/2013' AND m.home_goal > m.away_goal 149 | THEN 1 ELSE 0 END) AS matches_2012_2013, 150 | SUM(CASE WHEN m.season = '2013/2014' AND m.home_goal > m.away_goal 151 | THEN 1 ELSE 0 END) AS matches_2013_2014, 152 | SUM(CASE WHEN m.season = '2014/2015' AND m.home_goal > m.away_goal 153 | THEN 1 ELSE 0 END) AS matches_2014_2015 154 | FROM country AS c 155 | LEFT JOIN match AS m 156 | ON c.id = m.country_id 157 | GROUP BY c.name; 158 | 159 | -- Calculating percent with CASE and AVG 160 | 161 | -- (1) 162 | SELECT 163 | c.name AS country, 164 | COUNT(CASE WHEN m.home_goal > m.away_goal THEN m.id 165 | END) AS home_wins, 166 | COUNT(CASE WHEN m.home_goal < m.away_goal THEN m.id 167 | END) AS away_wins, 168 | COUNT(CASE WHEN m.home_goal = m.away_goal THEN m.id 169 | END) AS ties 170 | FROM country AS c 171 | LEFT JOIN matches AS m 172 | ON c.id = m.country_id 173 | GROUP BY country; 174 | 175 | -- (2) 176 | SELECT 177 | c.name AS country, 178 | AVG(CASE WHEN m.season= '2013/2014' AND m.home_goal = m.away_goal THEN 1 179 | WHEN m.season='2013/2014' AND m.home_goal != m.away_goal THEN 0 180 | END) AS ties_2013_2014, 181 | AVG(CASE WHEN m.season='2014/2015' AND m.home_goal = m.away_goal THEN 1 182 | WHEN m.season='2014/2015' AND m.home_goal != m.away_goal THEN 0 183 | END) AS ties_2014_2015 184 | FROM country AS c 185 | LEFT JOIN matches AS m 186 | ON c.id = m.country_id 187 | GROUP BY country; 188 | 189 | -- (3) 190 | SELECT 191 | c.name AS country, 192 | ROUND(AVG(CASE WHEN m.season='2013/2014' AND m.home_goal = m.away_goal THEN 1 193 | WHEN m.season='2013/2014' AND m.home_goal != m.away_goal THEN 0 194 | END),2) AS pct_ties_2013_2014, 195 | ROUND(AVG(CASE WHEN m.season='2014/2015' AND m.home_goal = m.away_goal THEN 1 196 | WHEN m.season='2014/2015' AND m.home_goal != m.away_goal THEN 0 197 | END),2) AS pct_ties_2014_2015 198 | FROM country AS c 199 | LEFT JOIN matches AS m 200 | ON c.id = m.country_id 201 | GROUP BY country; --------------------------------------------------------------------------------