├── .gitignore ├── Advanced Select and Joins ├── 01- The Number of Employees Which Report to Each Employee │ └── README.md ├── 02- Primary Department for Each Employee │ └── README.md ├── 03- Triangle Judgement │ └── README.md ├── 04- Consecutive Numbers │ └── README.md ├── 05- Product Price at a Given Date │ └── README.md ├── 06- Last Person to Fit in the Bus │ └── README.md └── 07- Count Salary Categories │ └── README.md ├── Advanced String Functions, Regex, Clause ├── 01 Fix Names in a Table │ └── README.md ├── 02- Patients With a Condition │ └── README.md ├── 03 Delete Duplicate Emails │ └── README.md ├── 04- Second Highest Salary │ └── README.md ├── 05 Group Sold Products By The Date │ └── README.md ├── 06- List the Products Ordered in a Period │ └── README.md └── 07 Find Users With Valid E-Mails │ └── README.md ├── Basic Aggregate Functions ├── 01- Not Boring Movies │ └── README.md ├── 02- Average Selling Price │ └── README.md ├── 03- Project Employees I │ └── README.md ├── 04- Percentage of Users Attended a Contest │ └── README.md ├── 05- Queries Quality and Percentage │ └── README.md ├── 06 -Monthly Transactions I │ └── README.md ├── 07- Immediate Food Delivery II │ └── README.md └── 08 -Game Play Analysis IV │ └── README.md ├── Basic Joins ├── 01- Replace Employee ID With The Unique Identifier │ └── README.md ├── 02- Product Sales Analysis I │ └── README.md ├── 03- Customer Who Visited but Did Not Make Any │ └── README.md ├── 04- Rising Temperature │ └── README.md ├── 05- Average Time of Process per Machine │ └── README.md ├── 06- Employee Bonus │ └── README.md ├── 07- Students and Examinations │ └── README.md ├── 08- Managers with at Least 5 Direct Reports │ └── README.md └── 09- Confirmation Rate │ └── README.md ├── README.md ├── Select ├── 01- Recyclable and Low Fat Products │ └── README.md ├── 02-Find Customer Referee │ └── README.md ├── 03 -Big Countries │ └── README.md ├── 04-Article Views I │ └── README.md └── 05- Invalid Tweets │ └── README.md ├── Sorting and Grouping ├── 01- Number of Unique Subjects Taught by Each Teacher │ └── README.md ├── 02- User Activity for the Past 30 Days I │ └── README.md ├── 03- Product Sales Analysis III │ └── README.md ├── 04- Classes More Than 5 Students │ └── README.md ├── 05- Find Followers Count │ └── README.md ├── 06- Biggest Single Number │ └── README.md └── 07- Customers Who Bought All Products │ └── README.md └── Subqueries ├── 01- Employees Whose Manager Left the Company └── README.md ├── 02- Exchange Seats └── README.md ├── 03- Movie Rating └── README.md ├── 04- Restaurant Growth └── README.md ├── 05- Friend Requests II: Who Has the Most Friends └── README.md ├── 06- Investments in 2016 └── README.md └── 07- Department Top Three Salaries └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Hints.txt 2 | script.py -------------------------------------------------------------------------------- /Advanced Select and Joins/01- The Number of Employees Which Report to Each Employee/README.md: -------------------------------------------------------------------------------- 1 | # [The Number of Employees Which Report to Each Employee](https://leetcode.com/problems/the-number-of-employees-which-report-to-each-employee/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Report the ids and the names of all managers, the number of employees who report directly to them, and the average age of the reports rounded to the nearest integer. 6 | 7 | Return the result table ordered by employee_id. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

JOIN the table with itself

15 |
16 |
17 | Hint#2 18 |

Consider the first table as Managers and the second one as Employees

19 |
20 | 21 |
22 | Hint#3 23 |

Use INNER JOIN

24 |
25 | 26 |
27 | 28 |
29 | Explanation 30 | 31 | We are required to perform a self-JOIN on the Employees table. 32 | 33 | Let's designate the first instance of the table as the "Manager" and the second instance as the "Employee" who is being managed. 34 | 35 | For the linkage, we'll use the condition where the employee_id in the first table matches the reports_to in the second table (first_table.employee_id = second_table.reports_to). 36 | 37 | As mentioned to retrieve information on all managers, we will employ an INNER JOIN, as managers must have at least one employee reporting to them. 38 | 39 | Lastly, we will utilize the AVG() function to compute the average and then apply the ROUND() function to round the result. 40 |
41 | 42 |
43 | SQL Solution 44 | 45 | 46 | ```sql 47 | SELECT 48 | a.employee_id, 49 | a.name, 50 | count(b.reports_to) AS reports_count, 51 | ROUND( 52 | AVG(b.age) 53 | ) AS average_age 54 | FROM 55 | Employees a 56 | INNER JOIN Employees b ON a.employee_id = b.reports_to 57 | GROUP BY 58 | a.employee_id 59 | ORDER BY 60 | a.employee_id 61 | -- ROUND(something , 0) by default 62 | ``` 63 | 64 |
-------------------------------------------------------------------------------- /Advanced Select and Joins/02- Primary Department for Each Employee/README.md: -------------------------------------------------------------------------------- 1 | # [Primary Department for Each Employee](https://leetcode.com/problems/primary-department-for-each-employee/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Employees can belong to multiple departments. When the employee joins other departments, they need to decide which department is their primary department. Note that when an employee belongs to only one department, their primary column is 'N'. 6 | 7 | Report all the employees with their primary department. For employees who belong to one department, report their only department. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

How would you filter employees belonging to many department?

15 |
16 | 17 |
18 | Hint#2 19 |

If an employee beglongs to more than one then it will be very easy to find him and his primary department as it will be marked with primary_flag='Y' 20 |

21 |
22 | 23 |
24 | Hint#3 25 |

How would you filter employees belonging to only one department?

26 |
27 | 28 |
29 | Hint#4 30 |

Use subqueries :)

31 |
32 | 33 |
34 | Hint#5 35 |

Use WHERE IN Clause

36 |
37 | 38 |
39 | Hint#6 40 |

Joining the results will require as only a simple OR operator

41 |
42 | 43 |
44 | 45 |
46 | Explanation 47 | 48 | The first step is to find all the employees who belong to more than one department. This can be done by checking if the priamry_flag is 'Y' or not. If it is 'Y' then it means that the employee belongs to more than one department and this is the primary department. 49 | 50 | Then we have to find the rest of the employees who belong to only one department. This can be done by using a subquery. We can group the employees by their employee_id and then count the number of distinct departments they belong to. If the count is 1 then it means that the employee belongs to only one department. 51 | 52 | Now we have to join the results of the two queries. This can be done by using a simple OR operator. 53 | 54 |
55 | 56 |
57 | SQL Solution 58 | 59 | ```sql 60 | select e.employee_id ,e.department_id from employee e 61 | where e.primary_flag='Y' or e.employee_id in 62 | (select employee_id from employee group by employee_id having count(distinct department_id)=1); 63 | ``` 64 | 65 |
66 | -------------------------------------------------------------------------------- /Advanced Select and Joins/03- Triangle Judgement/README.md: -------------------------------------------------------------------------------- 1 | # [Triangle Judgement](https://leetcode.com/problems/triangle-judgement/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Report for every three line segments whether they can form a triangle. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Review the Triangle Inequality Theorem

15 |
16 |
17 | Hint#2 18 |

Use CASE Statement

19 |
20 | 21 |
22 | 23 |
24 | Explanation 25 | 26 | [Triangle inequality](https://www.mathsisfun.com/geometry/triangle-inequality-theorem.html) 27 |
28 | The triangle inequality states that for any triangle, the sum of the lengths of any two sides must be greater than the length of the remaining side. 29 | 30 | To report the status for every three line segments we can use 31 | CASE Statement 32 | 33 | A triangle is considered valid if the sum of any two sides is greater than the third side. Conversely, if the sum of any two sides is less than or equal to the remaining side, it does not form a valid triangle. 34 |
35 | 36 |
37 | SQL Solution 38 | 39 | 40 | ```sql 41 | SELECT * , 42 | ( 43 | CASE 44 | WHEN x+y<=z THEN 'No' 45 | WHEN x+z<=y THEN 'No' 46 | WHEN z+y<=x THEN 'No' 47 | ELSE 'Yes' 48 | END 49 | ) AS triangle 50 | FROM Triangle 51 | ``` 52 | 53 |
-------------------------------------------------------------------------------- /Advanced Select and Joins/04- Consecutive Numbers/README.md: -------------------------------------------------------------------------------- 1 | # [Consecutive Numbers](https://leetcode.com/problems/consecutive-numbers/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find all numbers that appear at least three times consecutively. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Note that the ID is an autoincrement column

15 |
16 | 17 |
18 | Hint#2 19 |

Use Self Joins

20 |
21 | 22 |
23 | Hint#3 24 |

How do you check if three numbers are consecutive?

25 |
26 | 27 |
28 | 29 |
30 | Explanation 31 | 32 | This is a medium problem but it is very simple :). 33 | 34 | First we need to understand that the ID column is an autoincrement column. This means that the ID column will always be in ascending order. This means that if we have three consecutive numbers then the difference between the first and the last number will be 2. 35 | 36 | Now we need to find all the numbers that appear at least three times consecutively. This can be done by using a self join. We can join the table with itself (three times) and check if the difference between the ID column of the first and the second table is 1 and the difference between the ID column of the second and the third table is 1. If this is true then it means that the three numbers are consecutive. 37 | 38 |
39 | 40 |
41 | SQL Solution 42 | 43 | ```sql 44 | select distinct i1.num as ConsecutiveNums from 45 | logs i1,logs i2,logs i3 46 | where i1.id = i2.id-1 and i2.id = i3.id-1 and i1.num=i2.num and i2.num=i3.num; 47 | ``` 48 | 49 |
50 | -------------------------------------------------------------------------------- /Advanced Select and Joins/05- Product Price at a Given Date/README.md: -------------------------------------------------------------------------------- 1 | # [Product Price at a Given Date](https://leetcode.com/problems/product-price-at-a-given-date/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the prices of all products on 2019-08-16. Assume the price of all products before any change is 10. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

15 | What is the answer for a product that does not have any change_date on or before '2019-08-16' ? 16 |

17 |
18 |
19 | Hint#2 20 |

21 | What is the answer for a product that has at least onechange_date on or before '2019-08-16' ? 22 |

23 |
24 |
25 | Hint#3 26 |

27 | Use the EXISTS operator to check whether there is a record with specific properties 28 |

29 |
30 |
31 | Hint#4 32 |

33 | MySQL UNION operator allows you to combine two or more result sets of queries into a single result set 34 |

35 |
36 | 37 |
38 | 39 |
40 | Explanation 41 | 42 | Certainly, the answer is 10 for any product without a change_date on or before '2019-08-16'. To ensure this, we can utilize the NOT and EXISTS operators to confirm that there is no record associated with the product and having a change_date on or before '2019-08-16'. 43 | 44 | If a product has at least one record with a change_date on or before '2019-08-16', we need to retrieve the last changed_date to obtain the last_changed_price. 45 | 46 | We can dot this by using EXISTS operator as follows: 47 | - The change_date of the current record should be on or before '2019-08-16' 48 | - There is no record associated with the product on or before '2019-08-16' has a change_date greater than the change_date of the current record 49 | 50 | We can combine these results by using UNION ALL. 51 | 52 | We used UNION ALL instead of UNION because there are no duplicate records between both results and to improve the performance of our query. 53 |
54 | 55 |
56 | SQL Solution 57 | 58 | 59 | ```sql 60 | SELECT 61 | a.product_id, 62 | a.new_price as price 63 | FROM 64 | Products a 65 | WHERE 66 | a.change_date <= '2019-08-16' 67 | AND NOT EXISTS ( 68 | SELECT 69 | b.product_id 70 | FROM 71 | Products b 72 | WHERE 73 | b.change_date <= '2019-08-16' 74 | AND b.product_id = a.product_id 75 | AND a.change_date < b.change_date 76 | ) 77 | 78 | UNION --########################################### 79 | 80 | SELECT 81 | a.product_id, 82 | 10 as price 83 | FROM 84 | Products a 85 | WHERE 86 | NOT EXISTS( 87 | SELECT 88 | b.product_id 89 | FROM 90 | Products b 91 | WHERE 92 | a.product_id = b.product_id AND b.change_date <= '2019-08-16' 93 | ) 94 | ``` 95 | 96 |
-------------------------------------------------------------------------------- /Advanced Select and Joins/06- Last Person to Fit in the Bus/README.md: -------------------------------------------------------------------------------- 1 | # [Last Person to Fit in the Bus](https://leetcode.com/problems/last-person-to-fit-in-the-bus/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | There is a queue of people waiting to board a bus. However, the bus has a weight limit of 1000 kilograms, so there may be some people who cannot board. 6 | 7 | Find the person_name of the last person that can fit on the bus without exceeding the weight limit. The test cases are generated such that the first person does not exceed the weight limit. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Think in reverse? Let us try to find the persons who will not be able to the bus. Who would you do such a thing ?

15 |
16 | 17 |
18 | Hint#2 19 |

for each turn we need to find all turns that are less that or equal to it

20 |
21 | 22 |
23 | 24 |
25 | Explanation 26 | 27 | This problem seems simple but it is a bit tricky. We need to find the last person that can fit in the bus. So we need to find the person that has the maximum turn number that can fit in the bus. So we need to find the sum of the weights of all people that have a turn number less than or equal to the current turn number. Then we need to find the maximum turn number that has a sum of weights less than or equal to 1000. 28 | 29 | Ok, Think like this. We need to make a nested for loop that works like this: 30 | 31 | ```bash 32 | for each turn 33 | for each turn that is less than or equal to the current turn 34 | find the sum of weights 35 | if the sum of weights is less than or equal to 1000 36 | save the turn number as our answer 37 | ``` 38 | 39 | This can be done using a subquery. We can use the subquery to find the sum of weights for each turn that is less than or equal to the current turn. Then we can use the outer query to find the maximum turn number that has a sum of weights less than or equal to 1000. 40 | 41 |
42 | 43 |
44 | SQL Solution 45 | 46 | ```sql 47 | select person_name from queue as mainQ 48 | where 1000 >= ( 49 | select sum(weight) 50 | from queue 51 | where mainQ.turn >= turn 52 | ) 53 | order by turn desc 54 | limit 1; 55 | ``` 56 | 57 |
58 | -------------------------------------------------------------------------------- /Advanced Select and Joins/07- Count Salary Categories/README.md: -------------------------------------------------------------------------------- 1 | # [Count Salary Categories](https://leetcode.com/problems/count-salary-categories/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Write a solution to calculate the number of bank accounts for each salary category. The salary categories are: 6 | 7 | - "Low Salary": All the salaries strictly less than $20000. 8 | - "Average Salary": All the salaries in the inclusive range [$20000, $50000]. 9 | - "High Salary": All the salaries strictly greater than $50000. 10 | 11 | The result table must contain all three categories. If there are no accounts in a category, return 0. 12 | 13 | Return the result table in any order. 14 | 15 |
16 | Hints 17 | 18 |
19 | Hint#1 20 |

21 | MySQL UNION operator allows you to combine two or more result sets of queries into a single result set. 22 |

23 |
24 | 25 |
26 | 27 |
28 | Explanation 29 | 30 | Counting the matching records for each category is an easy task. 31 | 32 | Simply employ the COUNT() function and filter the records by applying conditions through the WHERE clause. 33 | 34 | To combine result sets from multiple SELECT statements, utilize the UNION operator. The choice between UNION and UNION ALL does not affect the outcome in this case, as the result set does not contain any duplicate entries. 35 |
36 | 37 |
38 | SQL Solution 39 | 40 | 41 | ```sql 42 | SELECT 43 | 'Low Salary' AS category, 44 | count(*) as accounts_count 45 | FROM 46 | Accounts 47 | WHERE income < 20000 48 | 49 | UNION -- ##################################### 50 | 51 | SELECT 52 | 'Average Salary' AS category, 53 | count(*) AS accounts_count 54 | FROM 55 | Accounts 56 | 57 | WHERE income BETWEEN 20000 AND 50000 58 | 59 | UNION -- ##################################### 60 | 61 | SELECT 62 | 'High Salary' AS category, 63 | count(*) AS accounts_count 64 | FROM 65 | Accounts 66 | WHERE income > 50000 67 | -- * symbol means all 68 | ``` 69 | 70 |
-------------------------------------------------------------------------------- /Advanced String Functions, Regex, Clause/01 Fix Names in a Table/README.md: -------------------------------------------------------------------------------- 1 | # [Fix Names in a Table](https://leetcode.com/problems/fix-names-in-a-table/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Fix the names so that only the first character is uppercase and the rest are lowercase. 6 | 7 | Return the result table ordered by user_id. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

15 | Try to divide the strings into two parts and work on each one of them 16 |

17 |
18 |
19 | Hint#2 20 |

How can you divide the string into substrings

21 |
22 |
23 | Hint#3 24 |

25 | The SUBSTRING function extracts a substring that starts at a specified position with a given length. 26 |
27 | SUBSTRING(source_string, position, length) 28 |

29 |
30 |
31 | Hint#4 32 |

How to convert a string into a lowercase/uppercase

33 |
34 |
35 | Hint#5 36 |

37 | The SQL UPPER function converts all the letters in a string into uppercase 38 |
39 | UPPER(string) 40 |
41 | The SQL LOWER function converts all the characters in a string into lowercase 42 |
43 | LOWER(string) 44 |

45 |
46 |
47 | Hint#6 48 |

How to concatenate two or more strings into one string

49 |
50 |
51 | Hint#7 52 |

53 | The SQL CONCAT function concatenates two or more strings into one string 54 | CONCAT(string1,string2,..) 55 |

56 |
57 | 58 |
59 | 60 |
61 | Explanation 62 | 63 | 76 | 77 |
78 | 79 |
80 | SQL Solution 81 | 82 | 83 | ```sql 84 | SELECT 85 | user_id, 86 | CONCAT( 87 | UPPER( 88 | SUBSTRING(name, 1, 1) 89 | ), 90 | LOWER( 91 | SUBSTRING(name, 2) 92 | ) 93 | ) AS name 94 | FROM 95 | Users 96 | ORDER BY 97 | user_id 98 | ``` 99 | 100 |
-------------------------------------------------------------------------------- /Advanced String Functions, Regex, Clause/02- Patients With a Condition/README.md: -------------------------------------------------------------------------------- 1 | # [Patients With a Condition](https://leetcode.com/problems/patients-with-a-condition/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the patient_id, patient_name, and conditions of the patients who have Type I Diabetes. Type I Diabetes always starts with DIAB1 prefix. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 |
12 | Hint#1 13 |

We can use the LIKE To check for strings matching

14 |
15 | 16 |
17 | Hint#2 18 |

Do not forget to check for the condition that DIAB1 is not the first word

19 |
20 | 21 |
22 |
23 | Explanation 24 | 25 | This is a very straightforward problem. 26 | 27 | We will just use the `LIKE` operator to check for the condition, and we will use the `%` wildcard to match any string that starts with `DIAB1` or has `DIAB1` in the middle. 28 | 29 |
30 |
31 | SQL Solution 32 | 33 | ```sql 34 | SELECT * FROM Patients WHERE conditions LIKE '% DIAB1%' OR conditions LIKE 'DIAB1%'; 35 | ``` 36 | 37 |
38 | -------------------------------------------------------------------------------- /Advanced String Functions, Regex, Clause/03 Delete Duplicate Emails/README.md: -------------------------------------------------------------------------------- 1 | # [Delete Duplicate Emails](https://leetcode.com/problems/delete-duplicate-emails/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Delete all duplicate emails, keeping only one unique email with the smallest id. 6 | 7 |
8 | Hints 9 | 10 |
11 | Hint#1 12 |

Think in an easier problem. How can you select the valid records

13 |
14 |
15 | Hint#2 16 |

Try to use SELF JOIN

17 |
18 |
19 | Hint#3 20 |

But we want to delete ?! , just a minor change :)

21 |
22 |
23 | Hint#4 24 |

A SQL DELETE statement can include JOIN operations

25 |
26 | 27 |
28 | 29 |
30 | Explanation 31 | 32 | The key ideas are 33 |
34 | 35 | - A SQL DELETE statement can include JOIN operations. 36 | 37 | - It can contain zero, one, or multiple JOIN operations. 38 | 39 | - The DELETE removes records that satisfy the JOIN and WHERE condition. 40 | - You must specify which table you want to delete from. 41 | 42 | In this problem we will use SELF JOIN to JOIN Person as a with itself as band specify table a in delete statement to delete the record from it. 43 | 44 | 45 | We will Join the Person and itself ON the following condition 46 |
47 | a.email = b.email 48 |
49 | and specify the records the should be deleted by the following condition 50 |
51 | a.id > b.id 52 |
53 | Which means that if a record in table a find a record in table b that have the same email then DELETE the record of table a if this record has a bigger ID than the record of table b 54 | 55 | 56 | 57 |
58 | 59 |
60 | SQL Solution 61 | 62 | 63 | ```sql 64 | DELETE a 65 | FROM 66 | Person a 67 | JOIN Person b ON a.email = b.email 68 | WHERE a.id > b.id 69 | 70 | --INNER JOIN Person b ON a.id > b.id AND a.email = b.email 71 | --You can combine them in join condition 72 | ``` 73 | 74 |
-------------------------------------------------------------------------------- /Advanced String Functions, Regex, Clause/04- Second Highest Salary/README.md: -------------------------------------------------------------------------------- 1 | # [Second Highest Salary](https://leetcode.com/problems/second-highest-salary/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the second highest salary from the Employee table. If there is no second highest salary, return null (return None in Pandas). 6 | 7 |
8 | Hints 9 | 10 |
11 | Hint#1 12 |

Think about subqueries

13 |
14 | 15 |
16 | Hint#2 17 |

Think about how would you get the second highest salary without a subquery

18 |
19 | 20 |
21 | Hint#3 22 |

The only purpose of the subquery is to handel the idea that the second highest may not exist

23 |
24 | 25 |
26 | 27 |
28 | Explanation 29 | 30 | To solve this problem, we need first to find the second highest salary, this is easy we need to sort the salaries in descending order and get the second one. But what if there is no second highest salary? In this case, we need to return null. To solve this problem we can use a subquery to get the second highest salary, and if it doesn't exist, we will get null as a result. 31 | 32 |
33 | 34 |
35 | SQL Solution 36 | 37 | ```sql 38 | 39 | select 40 | (select distinct Salary 41 | from Employee order by salary desc 42 | limit 1 offset 1) 43 | as SecondHighestSalary; 44 | 45 | 46 | ``` 47 | 48 |
49 | -------------------------------------------------------------------------------- /Advanced String Functions, Regex, Clause/05 Group Sold Products By The Date/README.md: -------------------------------------------------------------------------------- 1 | # [Group Sold Products By The Date](https://leetcode.com/problems/group-sold-products-by-the-date/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find for each date the number of different products sold and their names. 6 | 7 | The sold products names for each date should be sorted lexicographically. 8 | 9 | Return the result table ordered by sell_date. 10 | 11 |
12 | Hints 13 | 14 |
15 | Hint#1 16 |

17 | How can you concatenate strings from a group into a single string with various options ? 18 |

19 |
20 |
21 | Hint#2 22 |

23 | The MySQL GROUP_CONCAT() function is an aggregate function that concatenates strings from a group into a single string with various options. 24 |

25 |
26 |
27 | Hint#3 28 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

29 |
30 |
31 | 32 |
33 | Explanation 34 | 35 | 59 | 60 |
61 | 62 |
63 | SQL Solution 64 | 65 | 66 | ```sql 67 | SELECT 68 | sell_date, 69 | COUNT(DISTINCT product) AS num_sold, 70 | GROUP_CONCAT( 71 | DISTINCT product 72 | ORDER BY 73 | product 74 | ) AS products 75 | FROM 76 | Activities 77 | GROUP BY 78 | sell_date 79 | ORDER BY 80 | sell_date 81 | ``` 82 | 83 |
-------------------------------------------------------------------------------- /Advanced String Functions, Regex, Clause/06- List the Products Ordered in a Period/README.md: -------------------------------------------------------------------------------- 1 | # [List the Products Ordered in a Period](https://leetcode.com/problems/list-the-products-ordered-in-a-period/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the names of products that have at least 100 units ordered in February 2020 and their amount. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 |
12 | Hint#1 13 |

We want to get the something for each product, so think about grouping

14 |
15 |
16 | Hint#2 17 |

Use SQL BETWEEN 'yyyy-mm-dd' AND 'yyyy-mm-dd' to filter for a date

18 |
19 | 20 |
21 | Hint#3 22 |

Use SQL BETWEEN 'yyyy-mm-dd' AND 'yyyy-mm-dd' to filter for a date

23 |
24 | 25 |
26 | Hint#5 27 |

Use SQL HAVING clause to filter after using GROUP BY

28 |
29 | 30 |
31 | 32 |
33 | 34 | Explanation 35 | 36 | We have two tables, so we clearly need to join them. 37 | 38 | Now we have to use an Aggregate function to get the sum of the units ordered for each product, so we clearly need to use GROUP BY clause. 39 | 40 | Now we have to filter the result to get only the products that have at least 100 units ordered in February 2020, So first we need to get all the orders between 2020-02-1 and 2020-02-29 using BETWEEN clause, then we need to filter the result using HAVING clause. We will use an alias for the sum of the units ordered to make the code more readable, call it uint. 41 | 42 |
43 | 44 |
45 | 46 | SQL Solution 47 | 48 | ```sql 49 | 50 | select Products.product_name, sum(Orders. unit) as unit from Products 51 | join Orders on Orders.product_id=Products.product_id 52 | where Orders.order_date between '2020-02-1' and '2020-02-29' 53 | group by Products.product_id 54 | having unit >= 100; 55 | 56 | ``` 57 | 58 |
59 | -------------------------------------------------------------------------------- /Advanced String Functions, Regex, Clause/07 Find Users With Valid E-Mails/README.md: -------------------------------------------------------------------------------- 1 | # [Find Users With Valid E-Mails](https://leetcode.com/problems/find-users-with-valid-e-mails/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the users who have valid emails. 6 | 7 | Return the result table in any order. 8 |
9 | Hints 10 | 11 |
12 | Hint#1 13 |

14 | Try to use REGEXP operator to determine if a string matches a regular expression. 15 |
16 | expression REGEXP pattern 17 |

18 |
19 |
20 | Hint#2 21 |

To define the search criteria and pattern you can use Metacharacters

22 |
23 | 24 |
25 | 26 |
27 | Explanation 28 | 29 | First of all you have to be familiar with the following Metacharacters 30 |
    31 | 32 |
  1. 33 | The caret symbol ^ is used to check if a string starts with a certain character 34 |
  2. 35 |
  3. 36 | The dollar symbol $ is used to check if a string ends with a certain character 37 |
  4. 38 |
  5. 39 | The star symbol * matches zero or more occurrences of the pattern left to it 40 |
  6. 41 |
  7. 42 | Square brackets specifies a set of characters you wish to match 43 |
  8. 44 | 45 |
46 | With the help of REGEXP and Metacharacters the problem will be a piece of cake :) 47 | 69 |
70 | 71 |
72 | SQL Solution 73 | 74 | 75 | ```sql 76 | SELECT * 77 | FROM Users 78 | WHERE mail REGEXP '^[a-zA-Z][-._a-zA-Z0-9]*@leetcode[.]com$' 79 | ``` 80 | 81 |
-------------------------------------------------------------------------------- /Basic Aggregate Functions/01- Not Boring Movies/README.md: -------------------------------------------------------------------------------- 1 | # [Not Boring Movies](https://leetcode.com/problems/not-boring-movies/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Report the movies with an odd-numbered ID and a description that is not "boring". 6 | 7 | Return the result table ordered by rating in descending order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

SQL has a MOD(num1, num2) function that returns the value of num1 % num2 (with % beging the modulo operator)

15 |
16 | 17 |
18 | Hint#2 19 |

SQL has a NOT operator

20 |
21 | 22 |
23 | 24 |
25 | Explanation 26 | 27 | In order to solve this problem we need to use the mod function to get the odd numbered IDs and the not operator to get the movies with description not equal to "boring". 28 | 29 | Then, we can combine the two conditions using the and operator. 30 | 31 | Finally, we can order the result by rating in descending order using desc keyword. 32 | 33 |
34 | 35 |
36 | SQL Solution 37 | 38 | ```sql 39 | select id, movie, description, rating from Cinema 40 | where mod(id, 2)=1 and not description = "boring" 41 | order by rating desc; 42 | ``` 43 | 44 |
45 | -------------------------------------------------------------------------------- /Basic Aggregate Functions/02- Average Selling Price/README.md: -------------------------------------------------------------------------------- 1 | # [Average Selling Price](https://leetcode.com/problems/average-selling-price/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the average selling price for each product. average_price should be rounded to 2 decimal places. 6 | 7 | Return the result table in any order 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Use OUTER JOIN

15 |
16 |
17 | Hint#2 18 |

JOIN ON product_id AND purchase_date

19 |
20 |
21 | Hint#3 22 |

SQL has an aggregation function called SUM(expression) which calculate the sum of values in a set

23 |
24 |
25 | Hint#4 26 |

SQL has a ROUND(number, decimals) function which rounds a number to a specified number of decimal places.

27 |
28 |
29 | Hint#5 30 |

SQL has a COALESCE(val1 , val2 , ....) function which Return the first non-null value in a list

31 |
32 |
33 | Hint#6 34 |

Use GROUP BY clause to group a set of rows into a set of summary rows

35 |
36 | 37 |
38 | 39 |
40 | Explanation 41 | 42 | To find the average_price for each product we want should calculate the total money paid and the total units bought then divide them as follows 43 | 44 | 45 | $$ 46 | round(\frac{SUM(price \times units)}{SUM(units)} , 2) 47 | $$ 48 | 49 | we will JOIN these tables ON product_id and purchase_date. The purchase_date should be between start_date and end_date. 50 | 55 | But what if the total units is zero here we will have null. To solve this problem we can use COALESCE() function. This function will return the first non-null value in a list. 56 |
57 | 58 |
59 | SQL Solution 60 | 61 | 62 | 63 | ```sql 64 | SELECT 65 | Prices.product_id, 66 | COALESCE( 67 | ROUND( 68 | SUM(Prices.price * UnitsSold.units) / SUM(UnitsSold.units), 69 | 2 70 | ), 71 | 0 72 | ) AS average_price 73 | FROM 74 | Prices 75 | LEFT OUTER JOIN UnitsSold ON Prices.product_id = UnitsSold.product_id 76 | AND UnitsSold.purchase_date >= Prices.start_date 77 | AND UnitsSold.purchase_date <= end_date 78 | GROUP BY 79 | product_id 80 | ``` 81 |
-------------------------------------------------------------------------------- /Basic Aggregate Functions/03- Project Employees I/README.md: -------------------------------------------------------------------------------- 1 | # [Project Employees I](https://leetcode.com/problems/project-employees-i/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Report the average experience years of all the employees for each project, rounded to 2 digits. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

When we have more than one tables we must think about joins first

15 |
16 | 17 |
18 | Hint#2 19 |

SQL has a function AVG(column_name) returns the average value of that column

20 |
21 | 22 |
23 | Hint#3 24 |

Here we are asked to find the average for each project, we must think about Grouping

25 |
26 | 27 |
28 | 29 |
30 | Explanation 31 | 32 | We want to find the average experience years for each project, so we must join the two tables on the employee_id column, then we must group the result by the project_id column, and finally we must find the average of the experience_years column. 33 | 34 | When selecting the average of a column we must use the AVG(column_name) function, and to round the result to 2 digits we must use the ROUND() function, then we use AS to give the column an alias (average_years) 35 | 36 |
37 | 38 |
39 | SQL Solution 40 | 41 | ```sql 42 | select p.project_id, round(avg(e.experience_years),2) as average_years 43 | from Project p 44 | inner join Employee e on e.employee_id = p.employee_id 45 | group by p.project_id; 46 | ``` 47 | 48 |
49 | -------------------------------------------------------------------------------- /Basic Aggregate Functions/04- Percentage of Users Attended a Contest/README.md: -------------------------------------------------------------------------------- 1 | # [Percentage of Users Attended a Contest](https://leetcode.com/problems/percentage-of-users-attended-a-contest/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the percentage of the users registered in each contest rounded to two decimals. 6 | 7 | Return the result table ordered by percentage in descending order. In case of a tie, order it by contest_id in ascending order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

15 |
16 |
17 | Hint#2 18 |

Use subquery

19 |
20 | 21 |
22 | 23 |
24 | Explanation 25 | 26 | To find the percentage of the users registered in each contest we should count the number of user that have registered into a contest and the total number of users then divide. 27 |
28 |
29 | 40 |
41 | 42 |
43 | SQL Solution 44 | 45 | 46 | ```sql 47 | SELECT 48 | contest_id, 49 | ROUND( 50 | COUNT(user_id)/( 51 | SELECT 52 | COUNT(user_id) 53 | FROM 54 | Users 55 | )* 100 56 | , 2) AS percentage 57 | FROM 58 | Register 59 | GROUP BY 60 | contest_id 61 | ORDER BY 62 | percentage DESC, 63 | contest_id 64 | ``` 65 | 66 |
67 | -------------------------------------------------------------------------------- /Basic Aggregate Functions/05- Queries Quality and Percentage/README.md: -------------------------------------------------------------------------------- 1 | # [Queries Quality and Percentage](https://leetcode.com/problems/queries-quality-and-percentage/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | We define query quality as: 6 | 7 | The average of the ratio between query rating and its position. 8 | 9 | We also define poor_query_percentage as: 10 | 11 | The percentage of all queries with rating less than 3. 12 | 13 | Find each query_name, the quality and poor_query_percentage. 14 | 15 | Both quality and poor_query_percentage should be rounded to 2 decimal places. 16 | 17 | Return the result table in any order. 18 | 19 | 21 | 22 |
23 | Hints 24 | 25 |
26 | Hint#1 27 |

How SQL AVG function works ?
28 | AVG(column_name) = SUM(column_name) / COUNT(column_name) 29 |

30 |
31 | 32 |
33 | Hint#2 34 |

SQL has something called CASE Expression
35 | CASE WHEN condition THEN value1 ELSE value2 END 36 |

37 |
38 | 39 |
40 | Hint#3 41 |

Try combining AVG and CASE together

42 |
43 |
44 | Hint#5 45 |

Use Grouping

46 |
47 |
48 | Hint#4 49 |

Note that query_name may be NULL

50 |
51 | 52 |
53 | 54 |
55 | Explanation 56 | 57 | This problem is a bit tricky, we need to calculate the quality and poor_query_percentage for each query_name. 58 | 59 | First we must think about Grouping the data by query_name, then we can calculate the quality and poor_query_percentage for each group using AVG function. 60 | 61 | The quality is the average of the ratio between query rating and its position q1.rating / q1.position, so we can use AVG as following: AVG(q1.rating / q1.position) 62 | 63 | The poor_query_percentage is the percentage of all queries with rating less than 3, so how do we get the avarge of this condition ? we can use CASE expression to check if the rating is less than 3, then we can calculate the average of this condition, do not forget to multiply the avarage by 100 to get the percentage. 64 | 65 | Do not forget to round the results to 2 decimal places. 66 | 67 | Also do not forget to filter out the NULL values in query_name column. 68 | 69 |
70 | 71 |
72 | SQL Solution 73 | 74 | ```sql 75 | select 76 | q1.query_name as query_name, 77 | round(avg(q1.rating / q1.position), 2) as quality, 78 | round(100 * avg(case when q1.rating < 3 then 1 else 0 end), 2) as poor_query_percentage 79 | from Queries q1 80 | where q1.query_name is not null 81 | group by query_name; 82 | ``` 83 | 84 |
85 | 86 | 87 | -------------------------------------------------------------------------------- /Basic Aggregate Functions/06 -Monthly Transactions I/README.md: -------------------------------------------------------------------------------- 1 | # [Monthly Transactions I](https://leetcode.com/problems/monthly-transactions-i/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find for each month and country, the number of transactions and their total amount, the number of approved transactions and their total amount. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

How can you do some things when you find given conditions?

15 |
16 |
17 | Hint#2 18 |

Try it using CASE statement

19 |
20 |
21 | Hint#3 22 |

23 | SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition 24 |

25 |
26 |
27 | Hint#4 28 |

29 | SQL has an aggregation function called SUM(expression) which calculate the sum of values in a set 30 |

31 |
32 |
33 | Hint#5 34 |

35 | The DATE_FORMAT(date , format) function formats a date as specified. 36 |

37 |
38 |
39 | Hint#6 40 |

Use GROUP BY clause to group a set of rows into a set of summary rows

41 |
42 |
43 | 44 |
45 | Explanation 46 | 47 | 64 | 65 |
66 | 67 |
68 | SQL Solution 69 | 70 | 71 | ```sql 72 | SELECT 73 | DATE_FORMAT(trans_date, '%Y-%m') AS month, 74 | country, 75 | COUNT(state) AS trans_count, 76 | SUM( 77 | CASE WHEN state = 'approved' THEN 1 ELSE 0 END 78 | ) AS approved_count, 79 | SUM(amount) AS trans_total_amount, 80 | SUM( 81 | CASE WHEN state = 'approved' THEN amount ELSE 0 END 82 | ) AS approved_total_amount 83 | FROM 84 | Transactions 85 | GROUP BY 86 | month, 87 | country 88 | 89 | -- we can count the number of approved transactions in another way. 90 | 91 | -- COUNT( 92 | -- CASE WHEN state = 'approved' THEN 1 ELSE NULL END 93 | -- ) AS approved_count 94 | 95 | -- COUNT function will ignore NULL. 96 | ``` 97 | 98 |
-------------------------------------------------------------------------------- /Basic Aggregate Functions/07- Immediate Food Delivery II/README.md: -------------------------------------------------------------------------------- 1 | # [Immediate Food Delivery II](https://leetcode.com/problems/immediate-food-delivery-ii/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | If the customer's preferred delivery date is the same as the order date, then the order is called immediate; otherwise, it is called scheduled. 6 | 7 | The first order of a customer is the order with the earliest order date that the customer made. It is guaranteed that a customer has precisely one first order. 8 | 9 | Find the percentage of immediate orders in the first orders of all customers, rounded to 2 decimal places. 10 | 11 |
12 | Hints 13 | 14 |
15 | Hint#1 16 |

Immediate order occurres when order_date = customer_pref_delivery_date

17 |
18 | 19 |
20 | Hint#2 21 |

Use CASE Expression and the SUM function to find the number of Immediate orders. 22 | What will the whole sample sapce of orders be ?

23 |
24 | 25 |
26 | Hint#3 27 |

The sample space is the number of all orders in the table we can get it using COUNT(*)

28 |
29 | 30 |
31 | Hint#4 32 |

How would you find the MIN order_date for each customer ?

33 |
34 | 35 |
36 | Hint#5 37 |

Use WHERE IN clause (subquering)

38 |
39 | 40 |
41 | 42 |
43 | Explanation 44 | 45 | This problem is somewhat tough, we need to calculate the percentage of immediate orders in the first orders of all customers. 46 | 47 | First we need to find a way to find the immediate orders. But, before that we must also find a way to find the first order of each customer. 48 | 49 | To find the first order of each customer we will be using WHERE IN clause. 50 | 51 | The WHERE IN clause is used to filter the result of a subquery. It extracts the rows from the outer query and then compares it with the result of the subquery. It looks like this: 52 | 53 | ```sql 54 | WHERE (col1,col2) IN ( 55 | SELECT SOME_FUNCTION(col1), SOME_FUNCTION(col2) 56 | FROM tableX 57 | WHERE condition 58 | ); 59 | ``` 60 | 61 | Now we need to find the number of immediate orders, we can do that using CASE expression and SUM function. 62 | 63 | Since we did filter the Delivery table to have only the customer_id with the first order made we can now check the use SUM funtion on the CASE condition to find the number of order_date = customer_pref_delivery_date inside the CASE expression to find the count of immediate orders. 64 | 65 | We can divide the Summetion by the COUNT(\*) then multiply by 100 to get the percentage. Of course do not forget to round to 2 decimal places. 66 | 67 |
68 | 69 |
70 | SQL Solution 71 | 72 | ```sql 73 | SELECT ROUND(100 * SUM(CASE WHEN order_date = customer_pref_delivery_date THEN 1 ELSE 0 END) / COUNT(*), 2) AS immediate_percentage 74 | FROM Delivery 75 | WHERE (customer_id,order_date) IN ( 76 | SELECT customer_id, MIN(order_date) AS od 77 | FROM Delivery 78 | GROUP BY customer_id 79 | ); 80 | ``` 81 | 82 |
83 | -------------------------------------------------------------------------------- /Basic Aggregate Functions/08 -Game Play Analysis IV/README.md: -------------------------------------------------------------------------------- 1 | # [Game Play Analysis IV](https://leetcode.com/problems/game-play-analysis-iv/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the number of players that logged in for at least two consecutive days starting from their first login date, then divide that number by the total number of players. 6 | 7 |
8 | Hints 9 | 10 |
11 | Hint#1 12 |

13 | What if you have another column that has the first_login, 14 | The problem will be very easy, isn't it? 15 |

16 |
17 |
18 | Hint#2 19 |

20 | Try using WITH clause. It will help you to define a temporary data set. It will make your life easier. 21 |

22 |
23 |
24 | Hint#3 25 |

26 | The SQL MIN(expression) function returns the minimum value in a set of values 27 |

28 |
29 |
30 | Hint#4 31 |

32 | Try using window function. 33 |

34 |
35 | 36 |
37 | Hint#5 38 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

39 |
40 |
41 | Hint#6 42 |

43 | To subtract an interval e.g., a year, a month and a day to date, you can use the DATE_SUB() function. 44 |

45 |
46 |
47 | Hint#7 48 |

SQL has a ROUND(number, decimals) function which rounds a number to a specified number of decimal places.

49 |
50 |
51 | 52 |
53 | Explanation 54 | 55 | We want to count the number of players who logged in the next day of their first login day. 56 |
57 | we should determine the first login date for each player. 58 | Then when we find a player logged in the next day of this day we should put this player into account. 59 | 60 | 76 | 77 |
78 | 79 |
80 | SQL Solution 81 | 82 | 83 | ```sql 84 | WITH temp AS( 85 | SELECT 86 | *, 87 | MIN(event_date) OVER (Partition BY player_id) AS first_login 88 | -- over means that the function before it is a window function 89 | FROM 90 | Activity 91 | ) 92 | SELECT 93 | ROUND( 94 | ( 95 | SELECT 96 | COUNT(player_id) 97 | FROM 98 | temp 99 | WHERE 100 | DATE_SUB(event_date, INTERVAL 1 DAY) = first_login 101 | ) / ( 102 | SELECT 103 | COUNT(DISTINCT player_id) 104 | FROM 105 | Activity 106 | ), 107 | 2 108 | ) AS fraction 109 | 110 | 111 | ``` 112 | 113 |
-------------------------------------------------------------------------------- /Basic Joins/01- Replace Employee ID With The Unique Identifier/README.md: -------------------------------------------------------------------------------- 1 | # [Replace Employee ID With The Unique Identifier](https://leetcode.com/problems/replace-employee-id-with-the-unique-identifier/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Show the unique ID of each user, If a user does not have a unique ID replace just show null. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Use OUTER JOIN

15 |
16 |
17 | Hint#2 18 |

JOIN ON ID

19 |
20 | 21 |
22 | 23 |
24 | Explanation 25 | We want for every Employee to retrieve tha matching unique_ids. 26 |
27 | With the help of JOINS we can retrieve data from multiple tables but which one INNER JOIN or OUTER JOIN. 28 |
29 | The answer is OUTER JOIN because if the name does not have any unique_id we still need to retrieve it with NULL unique_id. 30 |
31 | SO we will JOIN Employees table with EmployeeUNI table ON id. 32 | 33 |
34 | 35 |
36 | SQL Solution 37 | 38 | 39 | ```sql 40 | SELECT 41 | EmployeeUNI.unique_id, 42 | Employees.name 43 | FROM 44 | Employees 45 | LEFT OUTER JOIN EmployeeUNI ON EmployeeUNI.id = Employees.id 46 | ; 47 | ``` 48 | 49 |
-------------------------------------------------------------------------------- /Basic Joins/02- Product Sales Analysis I/README.md: -------------------------------------------------------------------------------- 1 | # [Product Sales Analysis I](https://leetcode.com/problems/product-sales-analysis-i/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Report the product_name, year, and price for each sale_id in the Sales table. 6 | 7 | Return the resulting table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Use Inner Join

15 |
16 | 17 |
18 | Hint#2 19 |

Join the two tables on product_id

20 |
21 | 22 |
23 | 24 |
25 | Explanation 26 | 27 | We want to form a new table that contains the product_name, year, and price for each sale_id in the Sales table. We can do this by joining the Sales table with the Product table on the product_id column. This will give us the new desired table. 28 | 29 |
30 | 31 |
32 | SQL Solution 33 | 34 | ```sql 35 | SELECT Product.product_name, Sales.year, Sales.price 36 | FROM Sales INNER JOIN Product ON Product.product_id = Sales.product_id; 37 | ``` 38 | 39 |
40 | -------------------------------------------------------------------------------- /Basic Joins/03- Customer Who Visited but Did Not Make Any/README.md: -------------------------------------------------------------------------------- 1 | # [Customer Who Visited but Did Not Make Any](https://leetcode.com/problems/customer-who-visited-but-did-not-make-any-Transactionss/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the IDs of the users who visited without making any Transactions and the number of times they made these types of visits. 6 | 7 | Return the result table sorted in any order. 8 |
9 | Hints 10 | 11 |
12 | Hint#1 13 |

Use OUTER JOIN

14 |
15 |
16 | Hint#2 17 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

18 |
19 |
20 | Hint#3 21 |

You can use IS NULL to check if the value is null

22 |
23 | 24 |
25 | 26 |
27 | Explanation 28 | 29 | Let's rephrase the problem statement to make our life easier. 30 |
31 | For every customer count the number of visits that does not exist in Transactions Table such that counter > 0. 32 |
33 |
34 | First let's try to solve easier problem. we want to count the number of visits for every customer whether it exists in Transactions table or no. 35 |
36 | we can do this by selecting customer_id and counting visit_id using COUNT()function. 37 |
38 |
39 | The last thing we don't want to take the visits that exist in Transactions table into account, so we can left join Transactions table on visit_id and that will allow us to have NULL information about Transactions (which means that the Visits.visit_id doesn't have matching information in Transactions table or doesn't exists) then filter these record using WHERE clause and IS NULL operator. 40 |
41 | 42 |
43 | SQL Solution 44 | 45 | 46 | ```sql 47 | SELECT 48 | customer_id, 49 | COUNT(Visits.visit_id) AS count_no_trans 50 | FROM 51 | Visits 52 | LEFT OUTER JOIN Transactions ON Transactions.visit_id = Visits.visit_id 53 | WHERE 54 | Transactions_id IS NULL 55 | GROUP BY 56 | customer_id 57 | ; 58 | ``` 59 | 60 |
-------------------------------------------------------------------------------- /Basic Joins/04- Rising Temperature/README.md: -------------------------------------------------------------------------------- 1 | # [Rising Temperature](https://leetcode.com/problems/rising-temperature/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find all dates' Id with higher temperatures compared to its previous dates (yesterday). 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 |
12 | 13 |
14 | Hint#1 15 |

Use Self Join

16 |
17 | 18 |
19 | Hint#2 20 |

SQL has a function called DATEDIFF("date1","date2") to find the diffrence between two dates in days

21 |
22 | 23 |
24 | Hint#3 25 |

select the rows where the temperature of the first table is greater than the temperature of second table (using self joins)

26 |
27 | 28 |
29 | 30 |
31 | Explanation 32 | 33 | The problem asks to find the dates' Id with higher temperatures compared to its previous dates (yesterday). We can do this by joining the Weather table with itself and selecting only the dates form the first table where the temperature of the first table is greater than the temperature of second table. We can use the DATEDIFF("date1","date2") function to find the diffrence between two dates. 34 | 35 |
36 | 37 |
38 | SQL Solution 39 | 40 | ```sql 41 | SELECT Weather1.id as Id 42 | FROM Weather Weather1,Weather Weather2 43 | WHERE Weather1.temperature > Weather2.temperature AND DATEDIFF(Weather1.recordDate, Weather2.recordDate)=1; 44 | ``` 45 | 46 |
47 | -------------------------------------------------------------------------------- /Basic Joins/05- Average Time of Process per Machine/README.md: -------------------------------------------------------------------------------- 1 | # [Average Time of Process per Machine](https://leetcode.com/problems/average-time-of-process-per-machine/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the machine_id along with the average time as processing_time, which should be rounded to 3 decimal places. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Can you multiply timestamp with -1 when activity is start

15 |
16 |
17 | Hint#2 18 |

Try it using CASE statement.

19 |
20 |
21 | Hint#3 22 |

SQL has a ROUND(number, decimals) function which rounds a number to a specified number of decimal places.

23 |
24 |
25 | Hint#4 26 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

27 |
28 |
29 | Hint#5 30 |

SQL has an aggregation function called SUM(expression) which calculate the sum of values in a set

31 |
32 | 33 |
34 | 35 |
36 | Explanation 37 | 38 | Let's rephrase the problem statement to make our life easier. 39 |
40 | For every machine evaluate the following 41 | 42 | $$ 43 | round( \frac{(timestamp_{end}) - sum(timestamp_{start})}{count(process)} , 3) 44 | $$ 45 | 46 |
47 | The easiest way is to solve this problem is to use aggregation functions. 48 |
49 |
50 | First we need to calculate the time of all process , we need to sum 51 | end_time - start_time , with the help of CASE statement we can negate start_time then add the result to the time using SUM() function. 52 |
53 |
54 | Second we want to COUNT the number of process , we can use COUNT() function but we should divide it with 2 because every process has start_time and end_time so it will be calculated twice. 55 |
56 |
57 | Finally, divide thetime with the number of process then ROUND the result to 3 decimal places using ROUND(number , decimals) function. 58 | 59 |
60 | 61 |
62 | SQL Solution 63 | 64 | 65 | ```sql 66 | SELECT 67 | machine_id, 68 | ROUND( 69 | SUM( 70 | CASE WHEN activity_type = 'start' THEN timestamp *-1 ELSE timestamp END 71 | )/( 72 | COUNT(process_id)/ 2 73 | ), 74 | 3 75 | ) AS processing_time 76 | FROM 77 | Activity 78 | GROUP BY 79 | ac.machine_id 80 | ``` 81 | 82 |
-------------------------------------------------------------------------------- /Basic Joins/06- Employee Bonus/README.md: -------------------------------------------------------------------------------- 1 | # [Employee Bonus](https://leetcode.com/problems/employee-bonus/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Report the name and bonus amount of each employee with a bonus less than 1000. If there is no bonus for an employee, the bounce should be reported as NULL. 6 | 7 |
8 | Hints 9 | 10 |
11 | Hint#1 12 |

Use Joins

13 |
14 | 15 |
16 | Hint#2 17 |

Join on empId

18 |
19 | 20 |
21 | Hint#3 22 |

We should be using LEFT JOIN (Employee table be the left one)

23 |
24 | 25 |
26 | Hint#4 27 |

You can use IS NULL to check if the value is null

28 |
29 | 30 |
31 |
32 | Explanation 33 | 34 | We are asked to select the name and bonus amount of each employee with a bonus less than 1000. If there is no bonus for an employee, the bounce should be reported as NULL. 35 | 36 | First We must use a left join to make sure that every record in the Employee table is included in the result set and if there is no matching bounce (No mathcing Bouns.empId for a specific Employee.empId) in the Bonus table, the bounce will be set to NULL. 37 | 38 | Now to the where clause, we must select the records with a bonus less than 1000 or the records with a NULL bonus. 39 | 40 |
41 | 42 |
43 | SQL Solution 44 | 45 | ```sql 46 | SELECT Employee.name, Bonus.bonus FROM Employee 47 | LEFT JOIN Bonus 48 | ON Employee.empId = Bonus.empId 49 | WHERE Bonus.bonus < 1000 OR Bonus.bonus IS NULL; 50 | ``` 51 | 52 |
53 | -------------------------------------------------------------------------------- /Basic Joins/07- Students and Examinations/README.md: -------------------------------------------------------------------------------- 1 | # [Students and Examinations](https://leetcode.com/problems/students-and-examinations/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the number of times each student attended each exam. 6 | 7 | Return the result table ordered by student_id and subject_name. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Use Multiple Joins

15 |
16 |
17 | Hint#2 18 |

Use CROSS JOIN with subjects and OUTER JOIN with Examinations

19 |
20 |
21 | Hint#3 22 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

23 |
24 |
25 | Hint#4 26 |

Use GROUP BY clause to group a set of rows into a set of summary rows

27 |
28 |
29 | Hint#5 30 |

Use ORDER BY clause to sort a set of rows in ASC or DESC

31 |
32 |
33 | Hint#6 34 |

Use AND operator to combine more than one condition

35 |
36 |
37 | 38 |
39 | Explanation 40 | 41 | Let's rephrase the problem statement to make our life easier. 42 |
43 | for every record in the combination of student and subject count how many times it exists in Examinations table. 44 |
45 |
46 | First, let's make the combination of studentsandsubjects.It's done easily using CROSS JOIN. 47 |
48 |
49 | Second, JOIN Examinations table ON student_id and subject_id 50 | Then count Examinations.student_id or Examinations.subject_name using COUNT()function grouped by student_id and subject_name. 51 |
52 |
53 | Finally, Order the result Using ORDER BY clause in ascending order(ASC). 54 |
55 | 56 |
57 | SQL Solution 58 | 59 | 60 | ```sql 61 | SELECT 62 | Students.student_id, 63 | Students.student_name, 64 | Subjects.subject_name, 65 | COUNT(Examinations.student_id) AS attended_exams 66 | FROM 67 | Students 68 | CROSS JOIN Subjects 69 | LEFT OUTER JOIN Examinations ON Students.student_id = Examinations.student_id 70 | AND Subjects.subject_name = Examinations.subject_name 71 | GROUP BY 72 | Students.student_id, 73 | Subjects.subject_name 74 | ORDER BY 75 | Students.student_id, 76 | Subjects.subject_name 77 | ; 78 | -- I preferred to use CROSS JOIN because no need to specify any condition and CROSS JOIN does not have the ON or USING clause also you can use another type of JOINS 79 | 80 | ``` 81 | 82 |
-------------------------------------------------------------------------------- /Basic Joins/08- Managers with at Least 5 Direct Reports/README.md: -------------------------------------------------------------------------------- 1 | # [Managers with at Least 5 Direct Reports](https://leetcode.com/problems/managers-with-at-least-5-direct-reports/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find managers with at least 5 direct reports. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Self join Employee's table with itself using INNER JOIN

15 |
16 | 17 |
18 | Hint#2 19 |

Use GROUP BY clause

20 |
21 |
22 | 23 |
24 | Explanation 25 | 26 | We want to find the managers with at least 5 direct reports. So we must join the Employee table with itself on the employee1.id = the employee2.managerId considering that the employee1 is the manager of employee2. 27 | 28 | To find the managers with at least 5 direct reports, we must count the number of direct reports for each manager. We can do this by grouping the result by the managerId and then counting the number of direct reports for each manager. We can then use the HAVING clause and COUNT function to filter out the managers with at least 5 direct reports. 29 | 30 |
31 | 32 |
33 | SQL Solution 34 | 35 | ```sql 36 | SELECT e1.name AS name 37 | FROM Employee e1 INNER JOIN Employee e2 ON e1.id = e2.managerId 38 | GROUP BY e2.managerId 39 | HAVING COUNT(e2.managerId) >= 5; 40 | ``` 41 | 42 |
43 | -------------------------------------------------------------------------------- /Basic Joins/09- Confirmation Rate/README.md: -------------------------------------------------------------------------------- 1 | # [Confirmation Rate](https://leetcode.com/problems/confirmation-rate/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | The confirmation rate of a user is the number of 'confirmed' messages divided by the total number of requested confirmation messages. The confirmation rate of a user that did not request any confirmation messages is 0. Round the confirmation rate to two decimal places. 6 | 7 | Find the confirmation rate of each user. 8 | 9 | Return the result table in any order. 10 | 11 |
12 | Hints 13 | 14 |
15 | Hint#1 16 |

How can you count the number of actions when action = confirmed, try it using CASE statement

17 |
18 |
19 | Hint#2 20 |

Use OUTER JOIN

21 |
22 |
23 | Hint#3 24 |

SQL has an aggregation function called SUM(expression) which calculate the sum of values in a set

25 |
26 |
27 | Hint#4 28 |

SQL has a ROUND(number, decimals) function which rounds a number to a specified number of decimal places.

29 |
30 |
31 | Hint#5 32 |

Use GROUP BY clause to group a set of rows into a set of summary rows

33 |
34 | 35 |
36 | 37 |
38 | Explanation 39 | Let's rephrase the problem statement to make our life easier. 40 |
41 | for each user divide the number of confirmed message with the total requested messages. 42 | 43 | $$ 44 | round(\frac{count(confirmed\\_messages)}{count(messages)} , 2) 45 | $$ 46 | 47 |
48 | First, count the total requested messages for each user. we can use COUNT() function to evaluate this easily. 49 |
50 |
51 | Second, count the confirmed messages for each user. we can use CASE statement with SUM() function to evaluate this as follows : if the message is confirmed add 1 to your sum otherwise add 0. 52 |
53 |
54 | Finally, divide confirmed messages by total requested messages then round the result to 2 decimals using ROUND(number , decimals) function. 55 |
56 | 57 |
58 | SQL Solution 59 | 60 | 61 | ```sql 62 | SELECT 63 | Signups.user_id, 64 | ROUND( 65 | SUM( 66 | CASE WHEN Confirmations.action = 1 THEN 1 ELSE 0 END 67 | ) / COUNT(Signups.user_id), 68 | 2 69 | ) AS confirmation_rate 70 | FROM 71 | Signups 72 | LEFT OUTER JOIN Confirmations ON Signups.user_id = Confirmations.user_id 73 | GROUP BY 74 | Signups.user_id 75 | ``` 76 | 77 |
78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Solutions for The LeetCode SQL 50 FREE Study Plan 2 | 3 | ### [The Study Plan](https://leetcode.com/studyplan/top-sql-50/) 4 | 5 | ### How is this repository organized? 6 | 7 | This repository is organized in the same way as the study plan. Each folder in this repository corresponds to a set of questions in the study plan. Each folder contains folders for each question in the set. Each question folder contains a README.md file that contains the solution for the question. 8 | 9 | The README.md is organized in the following way: 10 | 11 | - Problem Requirements: The LeetCode problem requirements, with some extra explanation if necessary. 12 | - Hints: Hints for the problem, you should read this part if you are stuck in the problem, try taking each one at a time and think about it for a bit 5-10 minutes. 13 | - Explanation: Explanation of the solution, you should read this part after reading all the hints, and after trying to solve the problem by yourself first. 14 | - SQL Solution: The SQL solution for the problem, you should read this part after reading the explanation in order for it to make some sense. 15 | 16 | #### Folder Structure 17 | 18 | ``` 19 | ├── Advanced Select and Joins 20 | │ ├── 01- The Number of Employees Which Report to Each Employee 21 | │ │ └── README.md 22 | │ ├── 02- Primary Department for Each Employee 23 | │ │ └── README.md 24 | │ ├── 03- Triangle Judgement 25 | │ │ └── README.md 26 | │ ├── 04- Consecutive Numbers 27 | │ │ └── README.md 28 | │ ├── 05- Product Price at a Given Date 29 | │ │ └── README.md 30 | │ ├── 06- Last Person to Fit in the Bus 31 | │ │ └── README.md 32 | │ └── 07- Count Salary Categories 33 | │ └── README.md 34 | ├── Advanced String Functions, Regex, Clause 35 | │ ├── 01 Fix Names in a Table 36 | │ │ └── README.md 37 | │ ├── 02- Patients With a Condition 38 | │ │ └── README.md 39 | │ ├── 03 Delete Duplicate Emails 40 | │ │ └── README.md 41 | │ ├── 04- Second Highest Salary 42 | │ │ └── README.md 43 | │ ├── 05 Group Sold Products By The Date 44 | │ │ └── README.md 45 | │ ├── 06- List the Products Ordered in a Period 46 | │ │ └── README.md 47 | │ └── 07 Find Users With Valid E-Mails 48 | │ └── README.md 49 | ├── Basic Aggregate Functions 50 | │ ├── 01- Not Boring Movies 51 | │ │ └── README.md 52 | │ ├── 02- Average Selling Price 53 | │ │ └── README.md 54 | │ ├── 03- Project Employees I 55 | │ │ └── README.md 56 | │ ├── 04- Percentage of Users Attended a Contest 57 | │ │ └── README.md 58 | │ ├── 05- Queries Quality and Percentage 59 | │ │ └── README.md 60 | │ ├── 06 -Monthly Transactions I 61 | │ │ └── README.md 62 | │ ├── 07- Immediate Food Delivery II 63 | │ │ └── README.md 64 | │ └── 08 -Game Play Analysis IV 65 | │ └── README.md 66 | ├── Basic Joins 67 | │ ├── 01- Replace Employee ID With The Unique Identifier 68 | │ │ └── README.md 69 | │ ├── 02- Product Sales Analysis I 70 | │ │ └── README.md 71 | │ ├── 03- Customer Who Visited but Did Not Make Any 72 | │ │ └── README.md 73 | │ ├── 04- Rising Temperature 74 | │ │ └── README.md 75 | │ ├── 05- Average Time of Process per Machine 76 | │ │ └── README.md 77 | │ ├── 06- Employee Bonus 78 | │ │ └── README.md 79 | │ ├── 07- Students and Examinations 80 | │ │ └── README.md 81 | │ ├── 08- Managers with at Least 5 Direct Reports 82 | │ │ └── README.md 83 | │ └── 09- Confirmation Rate 84 | │ └── README.md 85 | ├── README.md 86 | ├── Select 87 | │ ├── 01- Recyclable and Low Fat Products 88 | │ │ └── README.md 89 | │ ├── 02-Find Customer Referee 90 | │ │ └── README.md 91 | │ ├── 03 -Big Countries 92 | │ │ └── README.md 93 | │ ├── 04-Article Views I 94 | │ │ └── README.md 95 | │ └── 05- Invalid Tweets 96 | │ └── README.md 97 | ├── Sorting and Grouping 98 | │ ├── 01- Number of Unique Subjects Taught by Each Teacher 99 | │ │ └── README.md 100 | │ ├── 02- User Activity for the Past 30 Days I 101 | │ │ └── README.md 102 | │ ├── 03- Product Sales Analysis III 103 | │ │ └── README.md 104 | │ ├── 04- Classes More Than 5 Students 105 | │ │ └── README.md 106 | │ ├── 05- Find Followers Count 107 | │ │ └── README.md 108 | │ ├── 06- Biggest Single Number 109 | │ │ └── README.md 110 | │ └── 07- Customers Who Bought All Products 111 | │ └── README.md 112 | └── Subqueries 113 | ├── 01- Employees Whose Manager Left the Company 114 | │ └── README.md 115 | ├── 02- Exchange Seats 116 | │ └── README.md 117 | ├── 03- Movie Rating 118 | │ └── README.md 119 | ├── 04- Restaurant Growth 120 | │ └── README.md 121 | ├── 05- Friend Requests II: Who Has the Most Friends 122 | │ └── README.md 123 | ├── 06- Investments in 2016 124 | │ └── README.md 125 | └── 07- Department Top Three Salaries 126 | └── README.md 127 | ``` 128 | 129 | #### Our Template 130 | 131 | ````md 132 | # [Problem name](https://problem-link-on-leetcode.com) 133 | 134 | ### Problem Requirements: 135 | 136 | Problem requirements go here. 137 | 138 |
139 | Hints 140 | 141 |
142 | Hint#1-10 143 |

hint body goes here

144 |
145 | 146 |
147 | 148 |
149 | Explanation 150 | 151 | Explanation goes here. 152 | 153 |
154 | 155 |
156 | SQL Solution 157 | 158 | ```sql 159 | SQL code goes here 160 | ``` 161 | 162 |
163 | ```` 164 | -------------------------------------------------------------------------------- /Select/01- Recyclable and Low Fat Products/README.md: -------------------------------------------------------------------------------- 1 | # [Recyclable and Low Fat Products](https://leetcode.com/problems/recyclable-and-low-fat-products/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | find the ids of products that are both low fat and recyclable. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Use the AND operator to combine two conditions. 15 |

16 |
17 | 18 |
19 | 20 |
21 | Explanation 22 | 23 | The question is pretty straight forward. We just need to find the ids of products that are both low fat and recyclable. 24 | 25 | We can do this by using the WHERE clause and the AND operator. 26 | 27 | The WHERE clause will filter out all the products that are not low fat and recyclable. The AND operator will make sure that the products are both low fat and recyclable. 28 | 29 | The query will return the ids of the products that are both low fat and recyclable. 30 | 31 |
32 | 33 |
34 | SQL Solution 35 | 36 | ```sql 37 | select product_id from Products where low_fats="Y" and recyclable= "Y"; 38 | ``` 39 | 40 |
41 | -------------------------------------------------------------------------------- /Select/02-Find Customer Referee/README.md: -------------------------------------------------------------------------------- 1 | # [Find Customer Referee](https://leetcode.com/problems/find-customer-referee/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ## Problem Requirements: 4 | Find the names of the customer that are not referred by the customer with id = 2. 5 |
6 | Note: You can print the result in any order. 7 | 8 |
9 | Hints 10 |
11 |
12 | Hint#1 13 |

Use OR operator to combine more than one condition.

14 |
15 |
16 |
17 | 18 |
19 | Explanation 20 |

21 | Let's split the problem into two sub problems 22 |

26 |

27 | First retrieve the names using select statement then use where clause to filter all the names that does not have id = 2 in the corresponding row. 28 |

29 |

30 | But what if the referee_id is NULL , here we can use 31 | IS NULL operator to filter it. 32 |

33 |

34 | Finally combine both conditions using OR operator to make sure that if one of the conditions is satisfied the corresponding name will be retrieved. 35 |

36 |

37 |
38 | 39 |
40 | SQL Solution 41 | 42 | ```sql 43 | SELECT name 44 | FROM customer 45 | WHERE referee_id IS NULL OR referee_id <>2; 46 | -- equal operator = 47 | -- not equal operator <> 48 | -- not equal operator != 49 | ``` 50 |
51 | -------------------------------------------------------------------------------- /Select/03 -Big Countries/README.md: -------------------------------------------------------------------------------- 1 | # [Big Countries](https://leetcode.com/problems/big-countries/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | A country is big if: 6 | 7 | - it has an area of at least three million (i.e., 3000000 km2), or 8 | 9 | - it has a population of at least twenty-five million (i.e., 25000000). 10 | 11 | Find the name, population, and area of the big countries. 12 | 13 | Return the result table in any order. 14 | 15 |
16 | Hints 17 |
18 | 19 |
20 | Hint#1 21 |

Use the OR operator to combine two conditions. 22 |

23 |
24 | 25 |
26 | 27 |
28 | Explanation 29 | 30 |
31 | 32 | The question is pretty straight forward. We just need to find the name, population, and area of the big countries. 33 | 34 | We can do this by using the WHERE clause and the OR operator. 35 | 36 | The WHERE clause will filter out all the countries that are not big. The OR operator will make sure that the countries are either big in area or population. 37 | 38 |
39 | 40 |
41 | SQL Solution 42 |
43 | 44 | ```sql 45 | SELECT name,area,population FROM World WHERE area >= 3000000 OR population >= 25000000; 46 | ``` 47 | 48 |
49 | -------------------------------------------------------------------------------- /Select/04-Article Views I/README.md: -------------------------------------------------------------------------------- 1 | # [Article Views I](https://leetcode.com/problems/article-views-i/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find all the authors that viewed at least one of their own articles. 6 | 7 | NOTE: Print the result table sorted by id in ascending order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Use DISTINCT to avoid duplicates.

15 |
16 | 17 |
18 | 19 |
20 | Explanation 21 | 22 |

23 | Let's divide the problem into two sub problems. 24 |

28 |

29 | First retrieve the authors using select statement then use where clause to filter all the authors that satisfy the following condition author_id = viewer_id in the corresponding row. 30 |
31 | This criterion indicates that the author has viewed the current article. 32 |

33 |

34 | But what if the author's id is duplicated , here we can use 35 | DISTINCT clause to avoid that. 36 |

37 |

38 | 39 |
40 | 41 |
42 | SQL Solution 43 | 44 | 45 | ```sql 46 | SELECT DISTINCT author_id AS id 47 | FROM Views 48 | WHERE author_id = viewer_id 49 | ORDER BY author_id 50 | ; 51 | ``` 52 | 53 |
-------------------------------------------------------------------------------- /Select/05- Invalid Tweets/README.md: -------------------------------------------------------------------------------- 1 | # [Invalid Tweets](https://leetcode.com/problems/invalid-tweets/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the IDs of the invalid tweets. The tweet is invalid if the number of characters used in the content of the tweet is strictly greater than 15 . 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

There is a function in SQL called LENGTH that returns the number of characters of a string. 15 |

16 |
17 | 18 |
19 | 20 |
21 | Explanation 22 | 23 | We need to find the IDs of the tweets that are invalid. A tweet is invalid if the number of characters used in the content of the tweet is strictly greater than 15 . 24 | 25 | We can do this by using the WHERE clause and the LENGTH function. 26 | 27 | The LENGTH function will return the number of characters in the content of the tweet. The WHERE clause will filter out all the tweets that are not invalid (Their length is strictly greater than 15). 28 | 29 |
30 | 31 |
32 | SQL Solution 33 | 34 | ```sql 35 | SELECT tweet_id from Tweets where LENGTH(content) > 15; 36 | ``` 37 | 38 |
39 | -------------------------------------------------------------------------------- /Sorting and Grouping/01- Number of Unique Subjects Taught by Each Teacher/README.md: -------------------------------------------------------------------------------- 1 | # [Number of Unique Subjects Taught by Each Teacher](https://leetcode.com/problems/number-of-unique-subjects-taught-by-each-teacher/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Calculate the number of unique subjects each teacher teaches in the university. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

What do we normally think about when here the word each ?

15 |
16 | 17 |
18 | Hint#2 19 |

Think about Grouping

20 |
21 | 22 |
23 | Hint#3 24 |

You can use COUNT(DISTINCT column_name) to count the unique values in the column

25 |
26 | 27 |
28 | 29 |
30 | Explanation 31 | 32 | This question is a simple grouping question. 33 | 34 | First When we see the word each we think about grouping. We will group by the teacher_id. 35 | 36 | Then we need to count the number of unique subjects each teacher teaches. We can use the COUNT(DISTINCT subject_id) to count the number of unique values of subject_id in the column. 37 | 38 |
39 | 40 |
41 | SQL Solution 42 | 43 | ```sql 44 | select teacher_id,count(distinct subject_id) as cnt from Teacher 45 | group by teacher_id; 46 | ``` 47 | 48 |
49 | -------------------------------------------------------------------------------- /Sorting and Grouping/02- User Activity for the Past 30 Days I/README.md: -------------------------------------------------------------------------------- 1 | # [User Activity for the Past 30 Days I](https://leetcode.com/problems/user-activity-for-the-past-30-days-i/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the daily active user count for a period of 30 days ending 2019-07-27 inclusively. A user was active on someday if they made at least one activity on that day. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

15 |
16 |
17 | Hint#2 18 |

Use GROUP BY clause to group a set of rows into a set of summary rows

19 |
20 |
21 | Hint#3 22 |

23 | To remove duplicate rows from a result set, you can use the DISTINCT operator 24 |

25 |
26 |
27 | 28 |
29 | Explanation 30 | 31 | 46 | 47 |
48 | 49 |
50 | SQL Solution 51 | 52 | 53 | ```sql 54 | SELECT 55 | activity_date AS day, 56 | COUNT(DISTINCT user_id) AS active_users 57 | FROM 58 | Activity 59 | WHERE 60 | activity_date BETWEEN DATE_SUB('2019-07-27', INTERVAL 29 day) 61 | AND '2019-07-27' 62 | GROUP BY 63 | activity_date 64 | 65 | ``` 66 | 67 |
-------------------------------------------------------------------------------- /Sorting and Grouping/03- Product Sales Analysis III/README.md: -------------------------------------------------------------------------------- 1 | # [Product Sales Analysis III](https://leetcode.com/problems/product-sales-analysis-iii/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Select the product id, year, quantity, price for the first year of every product sold. 6 | 7 | Return the resulting table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

How would you filter the Sales table to only contain the first product sold

15 |
16 | 17 |
18 | Hint#2 19 |

How would you use the result of the previous filtering to find the answer to the problem?

20 |
21 | 22 |
23 | Hint#3 24 |

Think subqueries

25 |
26 | 27 |
28 | Hint#4 29 |

Think about WHERE IN clause

30 |
31 | 32 |
33 | 34 |
35 | Explanation 36 | 37 | It is not obvious how would we use subqueries to solve this problem. 38 | 39 | The key is to understand that we need to find the first year of every product sold. This means that we need to find the minimum year for every product. We can do this by grouping the table by product_id and then selecting the minimum year for every product. This will give us the first year of every product sold. Now we can use this result to filter the original table and get the desired result using WHERE IN clause. 40 | 41 |
42 | 43 |
44 | SQL Solution 45 | 46 | ```sql 47 | select product_id, year as first_year, quantity, price 48 | from Sales 49 | where (product_id,year) in ( 50 | select product_id,min(year) from Sales 51 | group by product_id 52 | ); 53 | ``` 54 | 55 |
56 | -------------------------------------------------------------------------------- /Sorting and Grouping/04- Classes More Than 5 Students/README.md: -------------------------------------------------------------------------------- 1 | # [Classes More Than 5 Students](https://leetcode.com/problems/classes-more-than-5-students/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find all the classes that have at least five students. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

15 |
16 |
17 | Hint#2 18 |

19 | To specify a condition for groups, you can use the HAVING clause. 20 |

21 |
22 | 23 |
24 | 25 |
26 | Explanation 27 | 28 | We need to find the classes that have at lease 5 students. 29 | 30 | But why we can not use where clause ? 31 | 32 | Because The WHERE clause applies the condition to individual rows before the rows are summarized into groups by the GROUP BY clause. However, the HAVING clause applies the condition to the groups after the rows are grouped into groups. 33 | 34 | 45 |
46 | 47 |
48 | SQL Solution 49 | 50 | 51 | ```sql 52 | SELECT 53 | class 54 | FROM 55 | Courses 56 | GROUP BY 57 | class 58 | HAVING 59 | COUNT(student) >= 5 60 | ``` 61 | 62 |
-------------------------------------------------------------------------------- /Sorting and Grouping/05- Find Followers Count/README.md: -------------------------------------------------------------------------------- 1 | # [Find Followers Count](https://leetcode.com/problems/find-followers-count/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | For each user, return the number of followers. 6 | 7 | Return the result table ordered by user_id in ascending order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

What do we normally think about when here the word each ?

15 |
16 | 17 |
18 | Hint#2 19 |

Think about Grouping

20 |
21 | 22 |
23 | Hint#3 24 |

Use SQL COUNT() function to count the number of followers

25 |
26 | 27 |
28 | 29 |
30 | Explanation 31 | 32 | This is a simple grouping question. 33 | 34 | First When we see the word each we think about grouping. We will group by the user_id. 35 | 36 | Then we need to count the number of followers for each user. We can use the COUNT() function to count the number of followers for each user. 37 | 38 | Finally, we need to order the result by user_id in ascending order using the ORDER BY clause and ASC keyword. 39 | 40 |
41 | 42 |
43 | SQL Solution 44 | 45 | ```sql 46 | SELECT user_id, COUNT(follower_id) AS followers_count 47 | FROM followers 48 | GROUP BY user_id 49 | ORDER BY user_id ASC; 50 | ``` 51 | 52 |
53 | -------------------------------------------------------------------------------- /Sorting and Grouping/06- Biggest Single Number/README.md: -------------------------------------------------------------------------------- 1 | # [Biggest Single Number](https://leetcode.com/problems/biggest-single-number/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the largest single number. If there is no single number, report null. 6 | 7 |
8 | Hints 9 | 10 |
11 | Hint#1 12 |

SQL has an aggregation function called COUNT(expression) which count all the rows that satisfy a specified condition

13 |
14 |
15 | Hint#2 16 |

17 | To specify a condition for groups, you use the HAVING clause. 18 |

19 |
20 |
21 | Hint#3 22 |

23 | To limit the number of rows returned by a select statement, you use the LIMIT clause 24 |

25 |
26 |
27 | Hint#4 28 |

29 | The MySQL IFNULL() function lets you return an alternative value if an expression is NULL 30 |

31 |
32 | 33 |
34 | 35 |
36 | Explanation 37 | 38 | 55 | 56 |
57 | 58 |
59 | SQL Solution 60 | 61 | 62 | ```sql 63 | SELECT 64 | IFNULL( 65 | ( 66 | SELECT 67 | num 68 | FROM 69 | MyNumbers 70 | GROUP BY 71 | num 72 | HAVING 73 | COUNT(num) = 1 74 | ORDER BY 75 | num DESC 76 | limit 77 | 1 78 | ), 79 | NULL 80 | ) AS num 81 | -- But why we can not use where clause ? 82 | 83 | -- Because The WHERE clause applies the condition to individual rows before the rows are summarized into groups by the GROUP BY clause. However, the HAVING clause applies the condition to the groups after the rows are grouped into groups. 84 | ``` 85 | 86 |
-------------------------------------------------------------------------------- /Sorting and Grouping/07- Customers Who Bought All Products/README.md: -------------------------------------------------------------------------------- 1 | # [Customers Who Bought All Products](https://leetcode.com/problems/customers-who-bought-all-products/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Report the customer ids from the Customer table that bought all the products in the Product table. 6 | 7 | Return the result table in any order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

How can we get all ids of products bought by a customer ?

15 |
16 | 17 |
18 | Hint#2 19 |

Group the customers table by customer_id

20 |
21 | 22 |
23 | Hint#3 24 |

How can we select all distinct product keys ?

25 |
26 | 27 |
28 | Hint#4 29 |

We can use a simple SELECT statment with COUNT function

30 |
31 | 32 |
33 | Hint#5 34 |

We can we filter the customer that bought all products?

35 |
36 | 37 |
38 | Hint#6 39 |

Use subqueries with HAVING clause, how can we combine both?

40 |
41 | 42 |
43 | 44 |
45 | Explanation 46 | 47 | This is a simple grouping problem but but you have to familiar with the concpet of Subqueries. 48 | 49 | Let's break down the solution into steps: 50 | 51 | - First, we need to get all the customers grouped by their ids to be able to count the number of products they bought. 52 | - Second, we need a way to find the number of products in the Product table, this can be done with a simple subquery using SELECT, we can use COUNT function to get the number of products. 53 | 54 | - Finally, we need to filter the customers that bought all products, this can be done with HAVING clause, we can use HAVING clause with COUNT function to count the number of products bought by each customer and compare it with the number of products in the Product table (got by the subquery described in the second point). 55 |
56 | 57 |
58 | SQL Solution 59 | 60 | ```sql 61 | select customer_id from Customer 62 | group by customer_id 63 | having count(distinct product_key) = (select count(product_key) from Product); 64 | ``` 65 | 66 |
67 | -------------------------------------------------------------------------------- /Subqueries/01- Employees Whose Manager Left the Company/README.md: -------------------------------------------------------------------------------- 1 | # [Employees Whose Manager Left the Company](https://leetcode.com/problems/employees-whose-manager-left-the-company/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the IDs of the employees whose salary is strictly less than $30000 and whose manager left the company. When a manager leaves the company, their information is deleted from the Employees table, but the reports still have their manager_id set to the manager that left. 6 | 7 | Return the result table ordered by employee_id. 8 | 9 |
10 | Hints 11 |
12 | Hint#1 13 |

How would you find what ids not in the Employees table ?

14 |
15 | 16 |
17 | Hint#2 18 |

Use WHERE IN clause

19 |
20 | 21 |
22 | 23 |
24 | Explanation 25 | 26 | this problem is simple, but the only catch is how would you filter the managers that left the company, since their information is deleted from the Employees table, but the reports still have their manager_id set to the manager that left. 27 | 28 | so we need to find the manager_id that is not in the Employees table, and then we can use WHERE IN clause to filter the employees that have manager_id that is not in the Employees table. 29 | 30 |
31 | 32 |
33 | 34 | SQL Solution 35 | 36 | ```sql 37 | select distinct employee_id 38 | from Employees 39 | where salary < 30000 and manager_id not in (select employee_id from Employees) 40 | order by employee_id; 41 | 42 | 43 | ``` 44 | 45 |
46 | -------------------------------------------------------------------------------- /Subqueries/02- Exchange Seats/README.md: -------------------------------------------------------------------------------- 1 | # [Exchange Seats](https://leetcode.com/problems/exchange-seats/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Write a query to swap the seat id of every two consecutive students. If the number of students is odd, the id of the last student is not swapped. 6 | 7 | Return the result table ordered by id in ascending order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

How to determine if a student should be swapped or not?

15 |
16 | 17 |
18 | Hint#2 19 |

A student will be swapped if and only if he is not the last student or the number of students is even.

20 |
21 | 22 |
23 | Hint#3 24 |

Suppose that a student will be swapped. What is the id of the student he or will be swapped with?

25 |
26 | 27 |
28 | Hint#4 29 |

If a student is going to be swapped, he will be swapped with the student having his id plus one or minus one depending on the parity of the student's id.

30 |
31 | 32 |
33 | 34 |
35 | Explanation 36 | 37 | We will use a subquery to get the student's name after swapping. We will change the student's name if he isn't the last student or the number of students is even. 38 | 39 | To swap the student's name, we will check the parity of the student id. If the student id is odd he will be given the name of the student having his id plus one. Otherwise, he will be given the name of the student having his id minus one. 40 | 41 |
42 | 43 |
44 | SQL Solution 45 | 46 | ```sql 47 | SELECT s.id AS id, 48 | IF( 49 | s.id < (SELECT count(*) FROM Seat) 50 | OR 51 | MOD((SELECT count(*) FROM Seat), 2) = 0 52 | , 53 | ( 54 | SELECT student 55 | FROM Seat 56 | WHERE id = IF(MOD(s.id, 2) = 1, s.id+1, s.id-1) 57 | ) 58 | , 59 | s.student 60 | ) as student 61 | FROM Seat as s 62 | ORDER BY id; 63 | ``` 64 | 65 |
66 | -------------------------------------------------------------------------------- /Subqueries/03- Movie Rating/README.md: -------------------------------------------------------------------------------- 1 | # [Movie Rating](https://leetcode.com/problems/movie-rating/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the name of the user who has rated the greatest number of movies. In case of a tie, return the lexicographically smaller user name. 6 | 7 | Find the movie name with the highest average rating in February 2020. In case of a tie, return the lexicographically smaller movie name. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Think of the query as two seperate problems

15 |
16 | 17 |
18 | Hint#2 19 |

For the first problem: we want to find something for each user, think about grouping

20 |
21 | 22 |
23 | Hint#3 24 |

For the first problem: how would you select the user who rated the most moives ?

25 |
26 | 27 |
28 | Hint#4 29 |

For the first problem: use count function, with order by clause

30 |
31 | 32 |
33 | Hint#5 34 |

For the second problem: think about gruoping again

35 |
36 | 37 |
38 | Hint#6 39 |

For the second problem: to find the desired month and year use SQL EXTRACT(YEAR_MONTH FROM date)=yyyymm

40 |
41 | 42 |
43 | Hint#6 44 |

For the second problem: use AVG function, with order by clause

45 |
46 | 47 |
48 | Hint#7 49 |

use sqlunion all to union the two select statments

50 |
51 | 52 |
53 |
54 | Explanation 55 | 56 |

57 | To solve this problem we need to think of it as two seperate problems, the first one is to find the user who rated the most movies, and the second one is to find the movie with the highest average rating in February 2020. 58 | 59 | for the first one, we need to find the user who rated the most movies, so we need to group by the user_id and count the number of movies for each user, then we need to order by the count in descending order, and if there is a tie we need to return the lexicographically smaller user name, so we need to order by the user name in ascending order. 60 | 61 | for the second one, we need to find the movie with the highest average rating in February 2020, so we need to group by the movie_id and calculate the average rating for each movie, then we need to order by the average rating in descending order, and if there is a tie we need to return the lexicographically smaller movie name, so we need to order by the movie name in ascending order. 62 | 63 | To join the two select statments we need to use union all to union the two select statments. 64 | 65 | Why union all and not union ? because union will remove the duplicate rows, and we don't want that, we want to return the two results in one table. 66 | 67 |

68 | 69 |
70 |
71 | SQL Solution 72 | 73 | ```sql 74 | (select Users.name as results from MovieRating 75 | inner join Users on Users.user_id = MovieRating.user_id 76 | group by MovieRating.user_id 77 | order by count(MovieRating.movie_id) desc, Users.name asc 78 | limit 1) 79 | union all 80 | (select Movies.title as results from MovieRating 81 | inner join Movies on MovieRating.movie_id = Movies.movie_id 82 | where extract(YEAR_MONTH FROM MovieRating.created_at) = 202002 83 | group by MovieRating.movie_id 84 | order by avg(MovieRating.rating) desc, Movies.title asc 85 | limit 1); 86 | 87 | 88 | ``` 89 | 90 |
91 | -------------------------------------------------------------------------------- /Subqueries/04- Restaurant Growth/README.md: -------------------------------------------------------------------------------- 1 | # [Restaurant Growth](https://leetcode.com/problems/restaurant-growth/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Compute the moving average of how much the customer paid in a seven days window (i.e., current day + 6 days before). average_amount should be rounded to two decimal places. 6 | 7 | Return the result table ordered by visited_on in ascending order. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

15 | What if you have a table that has a day and it's total amount paid by customers How can you solve the problem then ?! 16 |

17 |
18 |
19 | Hint#2 20 |

21 | Try to use With clause to define this temporary table and use it in your query. 22 |

23 |
24 |
25 | Hint#3 26 |

27 | Use SELF JOIN to match every day with other days in it's week 28 |

29 |
30 |
31 | Hint#4 32 |

33 | To calculate the difference between two dates, you use the DATEDIFF()function. 34 |
35 | DATEDIFF ( datepart , startdate , enddate ) 36 |

37 |
38 |
39 | Hint#5 40 |

41 | How can you skip some record ? 42 |

43 |
44 |
45 | Hint#6 46 |

47 | The OFFSET offset clause skips the offset rows before beginning 48 |
49 | LIMIT row_count OFFSET offset 50 |

51 |
52 | 53 |
54 | 55 |
56 | Explanation 57 | 58 | Imagine that we have another table that contains day and the total amount paid by customers who visited the restaurant in this day How can we solve the problem now. 59 | 60 | 80 | 81 | But the problem is how can we git this table :) 82 | 83 | With help of With clause we can do this easily. 84 | 85 | The WITH clause, also known as a Common Table Expression (CTE), is used to define a temporary result set that can be referred to within the context of a SELECT, INSERT, UPDATE, or DELETE statement. It helps to simplify complex queries by breaking them into more manageable and readable parts. 86 | 87 | The basic syntax of a WITH clause is as follows: 88 | ```sql 89 | WITH cte_name (column1, column2, ...) AS ( 90 | -- Query that defines the CTE 91 | SELECT column1, column2, ... 92 | FROM some_table 93 | WHERE some_condition 94 | ) 95 | -- The main query that references the CTE 96 | SELECT * 97 | FROM cte_name; 98 | 99 | ``` 100 |
101 | 102 |
103 | SQL Solution 104 | 105 | 106 | ```sql 107 | WITH temp AS 108 | ( 109 | SELECT visited_on 110 | ,SUM(amount) AS tot 111 | FROM Customer 112 | GROUP BY visited_on 113 | ORDER BY visited_on 114 | ) 115 | SELECT a.visited_on , SUM(b.tot) AS amount , ROUND(SUM(b.tot)/7 , 2) AS average_amount 116 | FROM temp a 117 | INNER JOIN temp b ON DATEDIFF(a.visited_on , b.visited_on) BETWEEN 0 AND 6 118 | GROUP BY a.visited_on 119 | ORDER BY a.visited_on 120 | limit 100000000 OFFSET 6 121 | -- Queries that have an associated WITH clause can also be written using nested 122 | -- sub-queries but doing so add more complexity to read/debug the SQL query. 123 | ``` 124 | 125 |
-------------------------------------------------------------------------------- /Subqueries/05- Friend Requests II: Who Has the Most Friends/README.md: -------------------------------------------------------------------------------- 1 | # [Friend Requests II: Who Has the Most Friends](https://leetcode.com/problems/friend-requests-ii-who-has-the-most-friends/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Find the person who have the most friends and the most friends number. 6 | 7 | The test cases are generated so that only one person has the most friends. 8 | 9 |
10 | Hints 11 | 12 |
13 | Hint#1 14 |

Being friends is bidirectional. If you accept someone's adding friend request, both you and the other person will have one more friend.

15 |
16 | 17 |
18 | Hint#2 19 |

We want to find something for each person, think about grouping

20 |
21 | 22 |
23 | Hint#3 24 |

We can use a subquery to be our new table which we run select statments on

25 |
26 | 27 |
28 |
29 | Explanation 30 | 31 | This is pertty tough problem, so we will try to break it down and make it easier to understand. 32 | 33 | First we need to understand the problem, we need to find the person who have the most friends, what does it mean for a person to have the most friends ? it means that this person have the most friends sent requests accepted + the most friends received requests accepted, we can think about these two as two seperate queries, then union them together. But be careful, we need to union them using union all not union, because union will remove the duplicates, and we don't want that, we also want to be carful and give the columns the same name, so we can use as to give them the same name, this will allow the union all to work as expected. 34 | 35 | Finaly, The easiest part, use the table, generated by the subquery, and group by the id, and order by the number of friends in descending order, and limit the result to one row. 36 | 37 |
38 |
39 | SQL Solution 40 | 41 | ```sql 42 | select A.id, sum(A.friends_count) as num from 43 | (select requester_id as id, count(requester_id) as friends_count from RequestAccepted 44 | group by requester_id 45 | union all 46 | select accepter_id as id, count(accepter_id) as friends_count from RequestAccepted 47 | group by accepter_id) A 48 | group by A.id 49 | order by num desc 50 | limit 1 51 | ``` 52 | 53 |
54 | -------------------------------------------------------------------------------- /Subqueries/06- Investments in 2016/README.md: -------------------------------------------------------------------------------- 1 | # [Investments in 2016](https://leetcode.com/problems/investments-in-2016/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | Report the sum of all total investment values in 2016 tiv_2016, for all policyholders who: 6 | 7 | - have the same tiv_2015 value as one or more other policyholders, and 8 | - are not located in the same city as any other policyholder (i.e., the (lat, lon) attribute pairs must be unique). 9 | 10 | Round tiv_2016 to two decimal places. 11 | 12 |
13 | Hints 14 | 15 |
16 | Hint#1 17 |

How to test for the existence of any record meeting specific criteria?

18 |
19 |
20 | Hint#2 21 |

The EXISTS operator is used to test for the existence of any record in a subquery

22 |
23 | 24 |
25 | 26 |
27 | Explanation 28 | 29 | 46 | 47 |
48 | 49 |
50 | SQL Solution 51 | 52 | 53 | ```sql 54 | SELECT ROUND(SUM(b.tiv_2016) , 2) AS tiv_2016 55 | FROM Insurance b 56 | WHERE NOT EXISTS( 57 | SELECT a.pid 58 | FROM Insurance a 59 | WHERE a.lat = b.lat AND a.lon = b.lon AND a.pid != b.pid 60 | ) 61 | AND EXISTS( 62 | SELECT a.pid 63 | FROM Insurance a 64 | WHERE a.tiv_2015 = b.tiv_2015 AND a.pid != b.pid 65 | ) 66 | -- The EXISTS operator returns true if the subquery contains any rows. 67 | -- Otherwise, it returns false. 68 | ``` 69 | 70 |
-------------------------------------------------------------------------------- /Subqueries/07- Department Top Three Salaries/README.md: -------------------------------------------------------------------------------- 1 | # [Department Top Three Salaries](https://leetcode.com/problems/department-top-three-salaries/description/?envType=study-plan-v2&envId=top-sql-50) 2 | 3 | ### Problem Requirements: 4 | 5 | A company's executives are interested in seeing who earns the most money in each of the company's departments. A high earner in a department is an employee who has a salary in the top three unique salaries for that department. 6 | 7 | Write a solution to find the employees who are high earners in each of the departments. 8 | 9 | Return the result table in any order. 10 | 11 | 17 | 18 |
19 | Explanation 20 | 21 | This is a hard problem, we will break it down into pieces to make it easier to understand. 22 | 23 | Of course, we will be doing some king of a subquery, but we will be using a window function to solve this problem. 24 | 25 | We need to find the top three salaries for each department, we can do that by using the `DENSE_RANK()` function, which will rank the salaries in descending order for each department, and we will select only the top three salaries for each department. 26 | 27 | Now let's see how we would break down the solution: 28 | 29 | - First we need to join the `employee` table with the `department` table, so we can get the department name for each employee. 30 | 31 | - Then we need to select the department name, employee name, and the salary for each employee. 32 | 33 | - Then we need to rank the salaries for each department in descending order, and select only the top three salaries for each department. 34 | 35 |
36 |
37 | SQL Solution 38 | 39 | ```sql 40 | select department, employee, salary 41 | from ( 42 | select 43 | d.name as department, 44 | e.name as employee, 45 | e.salary as salary, 46 | dense_rank() over (partition by d.name order by salary desc) AS rnk 47 | from employee e 48 | join department d 49 | on e.departmentId = d.id 50 | ) as rnk_tbl 51 | where rnk <= 3; 52 | ``` 53 | 54 |
55 | --------------------------------------------------------------------------------