├── hard ├── questions12 ├── Find median given frequency of numbers.sql ├── Department top three salaries.sql ├── Cumulative Salary.sql ├── Get the Second Most Recent Activity.sql ├── Average Salary: Departments VS Company.sql ├── Game Play Analysis 5.sql ├── Find the Subtasks That Did Not Execute.sql └── Find the quiet students in the exam.sql ├── investorsrelations ├── .pdf ├── AMZN-Q2-2021-Earnings-Release.pdf ├── FY21_Q3_Consolidated_Financial_Statements.pdf └── Facebook-Reports-Third-Quarter-2020-Results-2020.pdf ├── easy ├── Duplicate Emails.sql ├── Shortest Distance.sql ├── Classes more than 5 students.sql ├── Biggest Single number.sql ├── Second highest salary.sql ├── Find Customer Refree.sql ├── Delete duplicate emails.sql ├── Rising Temperature.sql ├── Customers who never order.sql ├── Convert Date Format.sql ├── Employees earning more than their managers.sql ├── Swap Salary.sql ├── Triangle Judgement.sql ├── Combine two tables.sql ├── Consecutive available seats.sql ├── Fix Names In A Table Problem.sql ├── Employee Bonus.sql ├── Invalid Tweets.sql ├── Find Followers Count.sql ├── Not Boring movies.sql ├── Recyclable and Low Fat Products.sql ├── Big Countries.sql ├── Actors who cooperated with Directors atleast three times.sql ├── patients with conditions.sql ├── Find Customers With Positive Revenue this Year.sql ├── Game Play Analysis 1.sql ├── Article views.sql ├── Game play analysis 2.sql ├── Find the team size.sql ├── Calculate Special Bonus.sql ├── Product's Price For Each Store Problem.sql ├── Customer placing the largest number of orders .sql ├── Project Employees 2.sql ├── Rearrange Products Table.sql ├── Product Sales Analysis 1.sql ├── Product Sales Analysis 2.sql ├── Group sold products by the date.sql ├── Find Users with invalid Emails.sql ├── Replace employee id with unique identifier.sql ├── Find Total Time Spent by Each Employee.sql ├── Immediate food delivery.sql ├── Fix product Name Format.sql ├── Friendly Movies streamed list.sql ├── Friend Requests 1.sql ├── Project Employees 1.sql ├── Create Session bar chart.sql ├── User activity for past 30 days 1.sql ├── Daily Leads and Partners.sql ├── Primary Department For Each Employee Problem.sql ├── Reported posts.sql ├── Sales Analysis 1.sql ├── Sales Analysis 3.sql ├── Students with invalid departments.sql ├── Ads performance.sql ├── Sales Person.sql ├── Queries quality and percentage.sql ├── Percentage of Users Attended a Contest.sql ├── User Activity for past 30 days 2.sql ├── Bank Account Summary ||.sql ├── Reformat department table.sql ├── Sales Analysis 2.sql ├── Ad-Free Sessions.sql ├── Top Travellers.sql ├── Customer Who Visited but Did Not Make Any Transactions.sql ├── Average selling price.sql ├── Number of comments per post.sql ├── Product's Worth Over Invoices Problem.sql ├── Sellers with no sales.sql ├── Average Time of Process per Machine.sql └── Warehouse Manager.sql ├── LICENSE ├── medium ├── Exchange Seats.sql ├── Find the Missing IDs.sql ├── Find the start and end number of continuous ranges.sql ├── Friend Requests 2.sql ├── Article Views 2.sql ├── Get highest answer rate question.sql ├── Game Play Analysis 4.sql ├── Apples _ Oranges.sql ├── Active Businesses.sql ├── Get the second most recent activity.sql ├── Strong Friendship.sql ├── Count Salary Categories.sql ├── Count student number in departments.sql ├── Active Users.sql ├── Game Play Analysis 3.sql ├── All people report to the given manager.sql ├── Activity Participants.sql ├── Grand Slam Titles.sql ├── Group Employees of the Same Salary.sql ├── Count the Number of Experiments.sql ├── Evaluate Boolean Expressions.sql ├── Confirmation Rate.sql ├── Count Apples and Oranges.sql └── Find Cutoff Score for Each School.sql └── README.md /hard/questions12: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /investorsrelations/.pdf: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /investorsrelations/AMZN-Q2-2021-Earnings-Release.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naiborhujosua/faang_sql_questions_postgresql/HEAD/investorsrelations/AMZN-Q2-2021-Earnings-Release.pdf -------------------------------------------------------------------------------- /investorsrelations/FY21_Q3_Consolidated_Financial_Statements.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naiborhujosua/faang_sql_questions_postgresql/HEAD/investorsrelations/FY21_Q3_Consolidated_Financial_Statements.pdf -------------------------------------------------------------------------------- /investorsrelations/Facebook-Reports-Third-Quarter-2020-Results-2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naiborhujosua/faang_sql_questions_postgresql/HEAD/investorsrelations/Facebook-Reports-Third-Quarter-2020-Results-2020.pdf -------------------------------------------------------------------------------- /easy/Duplicate Emails.sql: -------------------------------------------------------------------------------- 1 | -- Question 11 2 | -- Write a SQL query to find all duplicate emails in a table named Person. 3 | 4 | -- +----+---------+ 5 | -- | Id | Email | 6 | -- +----+---------+ 7 | -- | 1 | a@b.com | 8 | -- | 2 | c@d.com | 9 | -- | 3 | a@b.com | 10 | -- +----+---------+ 11 | -- For example, your query should return the following for the above table: 12 | 13 | -- +---------+ 14 | -- | Email | 15 | -- +---------+ 16 | -- | a@b.com | 17 | -- +---------+ 18 | 19 | 20 | -- Solution 21 | Select Email 22 | From Person 23 | group by Email 24 | having count(*) > 1 -------------------------------------------------------------------------------- /easy/Shortest Distance.sql: -------------------------------------------------------------------------------- 1 | -- Question 25 2 | -- Table point holds the x coordinate of some points on x-axis in a plane, which are all integers. 3 | 4 | 5 | -- Write a query to find the shortest distance between two points in these points. 6 | 7 | 8 | -- | x | next shortest 9 | -- |-----| 10 | -- | -1 | 0 1 11 | -- | 0 | 2 2 12 | -- | 2 | null null 13 | 14 | 15 | -- The shortest distance is '1' obviously, which is from point '-1' to '0'. So the output is as below: 16 | 17 | 18 | -- | shortest| 19 | -- |---------| 20 | -- | 1 | 21 | 22 | -- Solution 23 | select min(abs(abs(a.x)-abs(a.next))) as shortest 24 | from 25 | ( 26 | select x,lead(order by x) as next 27 | from point 28 | ) a 29 | -------------------------------------------------------------------------------- /easy/Classes more than 5 students.sql: -------------------------------------------------------------------------------- 1 | -- Question7 2 | -- There is a table courses with columns: student and class 3 | 4 | -- Please list out all classes which have more than or equal to 5 students. 5 | 6 | -- For example, the table: 7 | 8 | -- +---------+------------+ 9 | -- | student | class | 10 | -- +---------+------------+ 11 | -- | A | Math | 12 | -- | B | English | 13 | -- | C | Math | 14 | -- | D | Biology | 15 | -- | E | Math | 16 | -- | F | Computer | 17 | -- | G | Math | 18 | -- | H | Math | 19 | -- | I | Math | 20 | -- +---------+------------+ 21 | 22 | -- Solution 23 | select class 24 | from courses 25 | group by class 26 | having count(distinct student)>=5 -------------------------------------------------------------------------------- /easy/Biggest Single number.sql: -------------------------------------------------------------------------------- 1 | -- Question 24 2 | -- Table my_numbers contains many numbers in column num including duplicated ones. 3 | -- Can you write a SQL query to find the biggest number, which only appears once. 4 | 5 | -- +---+ 6 | -- |num| 7 | -- +---+ 8 | -- | 8 | 9 | -- | 8 | 10 | -- | 3 | 11 | -- | 3 | 12 | -- | 1 | 13 | -- | 4 | 14 | -- | 5 | 15 | -- | 6 | 16 | -- For the sample data above, your query should return the following result: 17 | -- +---+ 18 | -- |num| 19 | -- +---+ 20 | -- | 6 | 21 | -- Note: 22 | -- If there is no such number, just output null. 23 | 24 | 25 | -- Solution 26 | select num 27 | from 28 | (select num 29 | from my_numbers 30 | group by num 31 | having count(num) = 1) a 32 | order by num desc 33 | limit 1 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /easy/Second highest salary.sql: -------------------------------------------------------------------------------- 1 | -- Question 15 2 | -- Write a SQL query to get the second highest salary from the Employee table. 3 | 4 | -- +----+--------+ 5 | -- | Id | Salary | 6 | -- +----+--------+ 7 | -- | 1 | 100 | 8 | -- | 2 | 200 | 9 | -- | 3 | 300 | 10 | -- +----+--------+ 11 | -- For example, given the above Employee table, the query should return 200 as the second highest salary. 12 | -- If there is no second highest salary, then the query should return null. 13 | 14 | -- +---------------------+ 15 | -- | SecondHighestSalary | 16 | -- +---------------------+ 17 | -- | 200 | 18 | -- +---------------------+ 19 | 20 | 21 | -- Solution 22 | select max(salary) as SecondHighestSalary 23 | from employee 24 | where salary ! = (Select max(salary) 25 | from employee) -------------------------------------------------------------------------------- /easy/Find Customer Refree.sql: -------------------------------------------------------------------------------- 1 | -- Question 10 2 | -- Given a table customer holding customers information and the referee. 3 | 4 | -- +------+------+-----------+ 5 | -- | id | name | referee_id| 6 | -- +------+------+-----------+ 7 | -- | 1 | Will | NULL | 8 | -- | 2 | Jane | NULL | 9 | -- | 3 | Alex | 2 | 10 | -- | 4 | Bill | NULL | 11 | -- | 5 | Zack | 1 | 12 | -- | 6 | Mark | 2 | 13 | -- +------+------+-----------+ 14 | -- Write a query to return the list of customers NOT referred by the person with id '2'. 15 | 16 | -- For the sample data above, the result is: 17 | 18 | -- +------+ 19 | -- | name | 20 | -- +------+ 21 | -- | Will | 22 | -- | Jane | 23 | -- | Bill | 24 | -- | Zack | 25 | -- +------+ 26 | 27 | -- Solution 28 | Select name 29 | from customer 30 | where referee_id != 2 31 | or referee_id is NULL -------------------------------------------------------------------------------- /easy/Delete duplicate emails.sql: -------------------------------------------------------------------------------- 1 | -- Question 32 2 | -- Write a SQL query to delete all duplicate email entries in a table named Person, keeping only unique emails based on its smallest Id. 3 | 4 | -- +----+------------------+ 5 | -- | Id | Email | 6 | -- +----+------------------+ 7 | -- | 1 | john@example.com | 8 | -- | 2 | bob@example.com | 9 | -- | 3 | john@example.com | 10 | -- +----+------------------+ 11 | -- Id is the primary key column for this table. 12 | -- For example, after running your query, the above Person table should have the following rows: 13 | 14 | -- +----+------------------+ 15 | -- | Id | Email | 16 | -- +----+------------------+ 17 | -- | 1 | john@example.com | 18 | -- | 2 | bob@example.com | 19 | -- +----+------------------+ 20 | 21 | -- Solution 22 | Delete from Person 23 | where Id Not in 24 | (Select id From (Select Email, Min(Id) as 'id' From Person Group By Email) t) -------------------------------------------------------------------------------- /easy/Rising Temperature.sql: -------------------------------------------------------------------------------- 1 | -- Question 12 2 | -- Given a Weather table, write a SQL query to find all dates' Ids with higher temperature compared to its previous (yesterday's) dates. 3 | 4 | -- +---------+------------------+------------------+ 5 | -- | Id(INT) | RecordDate(DATE) | Temperature(INT) | 6 | -- +---------+------------------+------------------+ 7 | -- | 1 | 2015-01-01 | 10 | 8 | -- | 2 | 2015-01-02 | 25 | 9 | -- | 3 | 2015-01-03 | 20 | 10 | -- | 4 | 2015-01-04 | 30 | 11 | -- +---------+------------------+------------------+ 12 | -- For example, return the following Ids for the above Weather table: 13 | 14 | -- +----+ 15 | -- | Id | 16 | -- +----+ 17 | -- | 2 | 18 | -- | 4 | 19 | -- +----+ 20 | 21 | -- Solution 22 | select w1.id 23 | from weather w1,weather w2 24 | where w1.temperature > w2.temperature and datediff(w1.RecordDate,w2.RecordDate)=1 25 | -------------------------------------------------------------------------------- /easy/Customers who never order.sql: -------------------------------------------------------------------------------- 1 | -- Question 13 2 | -- Suppose that a website contains two tables, 3 | -- the Customers table and the Orders table. Write a SQL query to find all customers who never order anything. 4 | 5 | -- Table: Customers. 6 | 7 | -- +----+-------+ 8 | -- | Id | Name | 9 | -- +----+-------+ 10 | -- | 1 | Joe | 11 | -- | 2 | Henry | 12 | -- | 3 | Sam | 13 | -- | 4 | Max | 14 | -- +----+-------+ 15 | -- Table: Orders. 16 | 17 | -- +----+------------+ 18 | -- | Id | CustomerId | 19 | -- +----+------------+ 20 | -- | 1 | 3 | 21 | -- | 2 | 1 | 22 | -- +----+------------+ 23 | -- Using the above tables as example, return the following: 24 | 25 | -- +-----------+ 26 | -- | Customers | 27 | -- +-----------+ 28 | -- | Henry | 29 | -- | Max | 30 | -- +-----------+ 31 | 32 | 33 | -- Solution 34 | Select c.Name as Customers 35 | From Customers c 36 | left join Orders o 37 | on c.Id = o.CustomerId 38 | where o.Id is null -------------------------------------------------------------------------------- /easy/Convert Date Format.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Table Days 3 | +-------------+------+ 4 | | Column Name | Type | 5 | +-------------+------+ 6 | | day | date | 7 | +-------------+------+ 8 | -- day is the primary key for this table. 9 | -- Write an SQL query to convert each date in Days into a string formatted as “day_name, month_name day, year”. 10 | -- Return the result table in any order. 11 | -- The query result format is in the following example: 12 | 13 | -- Days table: 14 | +------------+ 15 | | day | 16 | +------------+ 17 | | 2022-04-12 | 18 | | 2021-08-09 | 19 | | 2020-06-26 | 20 | +------------+ 21 | 22 | -- Result table: 23 | +-------------------------+ 24 | | day | 25 | +-------------------------+ 26 | | Tuesday, April 12, 2022 | 27 | | Monday, August 9, 2021 | 28 | | Friday, June 26, 2020 | 29 | +-------------------------+ 30 | -- Please note that the output is case-sensitive. 31 | 32 | --Solution 33 | 34 | select to_char(day, "D,Month DD, YYYY") 35 | from Days -------------------------------------------------------------------------------- /easy/Employees earning more than their managers.sql: -------------------------------------------------------------------------------- 1 | -- Question 15 2 | -- The Employee table holds all employees including their managers. 3 | -- Every employee has an Id, and there is also a column for the manager Id. 4 | 5 | -- +----+-------+--------+-----------+ 6 | -- | Id | Name | Salary | ManagerId | 7 | -- +----+-------+--------+-----------+ 8 | -- | 1 | Joe | 70000 | 3 | 9 | -- | 2 | Henry | 80000 | 4 | 10 | -- | 3 | Sam | 60000 | NULL | 11 | -- | 4 | Max | 90000 | NULL | 12 | -- +----+-------+--------+-----------+ 13 | -- Given the Employee table, write a SQL query that finds out employees who earn more than their managers. 14 | -- For the above table, Joe is the only employee who earns more than his manager. 15 | 16 | -- +----------+ 17 | -- | Employee | 18 | -- +----------+ 19 | -- | Joe | 20 | -- +----------+ 21 | 22 | -- Solution 23 | Select e1.Name as Employee 24 | from Employee e1, Employee e2 25 | where e1.Salary > e2.Salary and e1.managerId = e2.id -------------------------------------------------------------------------------- /easy/Swap Salary.sql: -------------------------------------------------------------------------------- 1 | -- Question 22 2 | -- Given a table salary, such as the one below, that has m=male and f=female values. 3 | -- Swap all f and m values (i.e., change all f values to m and vice versa) with 4 | -- a single update statement and no intermediate temp table. 5 | 6 | -- Note that you must write a single update statement, DO NOT write any select statement for this problem. 7 | 8 | 9 | -- Example: 10 | 11 | -- | id | name | sex | salary | 12 | -- |----|------|-----|--------| 13 | -- | 1 | A | m | 2500 | 14 | -- | 2 | B | f | 1500 | 15 | -- | 3 | C | m | 5500 | 16 | -- | 4 | D | f | 500 | 17 | -- After running your update statement, the above salary table should have the following rows: 18 | -- | id | name | sex | salary | 19 | -- |----|------|-----|--------| 20 | -- | 1 | A | f | 2500 | 21 | -- | 2 | B | m | 1500 | 22 | -- | 3 | C | f | 5500 | 23 | -- | 4 | D | m | 500 | 24 | 25 | 26 | -- Solution 27 | update salary 28 | set sex = case when sex ="m" then "f" 29 | else "m" end 30 | -------------------------------------------------------------------------------- /easy/Triangle Judgement.sql: -------------------------------------------------------------------------------- 1 | -- Question 16 2 | -- A pupil Tim gets homework to identify whether three line segments could possibly form a triangle. 3 | 4 | 5 | -- However, this assignment is very heavy because there are hundreds of records to calculate. 6 | 7 | 8 | -- Could you help Tim by writing a query to judge whether these three sides can form a triangle, 9 | -- assuming table triangle holds the length of the three sides x, y and z. 10 | 11 | 12 | -- | x | y | z | 13 | -- |----|----|----| 14 | -- | 13 | 15 | 30 | 15 | -- | 10 | 20 | 15 | 16 | -- For the sample data above, your query should return the follow result: 17 | -- | x | y | z | triangle | 18 | -- |----|----|----|----------| 19 | -- | 13 | 15 | 30 | No | 20 | -- | 10 | 20 | 15 | Yes | 21 | 22 | 23 | -- Solution 24 | select x,y,z, 25 | case when x+y > z and x + z > y and y + z > x then "Yes" 26 | when x=y and x=z and y=z then "Yes" 27 | else "No" end as triangle 28 | from triangle 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /easy/Combine two tables.sql: -------------------------------------------------------------------------------- 1 | -- Question 14 2 | -- Table: Person 3 | 4 | -- +-------------+---------+ 5 | -- | Column Name | Type | 6 | -- +-------------+---------+ 7 | -- | PersonId | int | 8 | -- | FirstName | varchar | 9 | -- | LastName | varchar | 10 | -- +-------------+---------+ 11 | -- PersonId is the primary key column for this table. 12 | -- Table: Address 13 | 14 | -- +-------------+---------+ 15 | -- | Column Name | Type | 16 | -- +-------------+---------+ 17 | -- | AddressId | int | 18 | -- | PersonId | int | 19 | -- | City | varchar | 20 | -- | State | varchar | 21 | -- +-------------+---------+ 22 | -- AddressId is the primary key column for this table. 23 | 24 | 25 | -- Write a SQL query for a report that provides the following information for each person in the Person table, 26 | -- regardless if there is an address for each of those people: 27 | 28 | -- FirstName, LastName, City, State 29 | 30 | 31 | -- Solution 32 | Select p.FirstName,p.LastName,a.City,a.State 33 | from Person p left join Address a 34 | using(PersonId) -------------------------------------------------------------------------------- /hard/Find median given frequency of numbers.sql: -------------------------------------------------------------------------------- 1 | -- Question 107 2 | -- The Numbers table keeps the value of number and its frequency. 3 | 4 | -- +----------+-------------+ 5 | -- | Number | Frequency |cumsum | middle | range 6 | -- +----------+-------------| 7 | -- | 0 | 7 | 7 6 0,7 8 | -- | 1 | 1 | 8 6 7,8 9 | -- | 2 | 3 | 11 6 8,11 10 | -- | 3 | 1 | 12 6 11,12 11 | -- +----------+-------------+ 12 | -- In this table, the numbers are 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, so the median is (0 + 0) / 2 = 0. 13 | 14 | -- +--------+ 15 | -- | median | 16 | -- +--------| 17 | -- | 0.0000 | 18 | -- +--------+ 19 | -- Write a query to find the median of all numbers and name the result as median. 20 | 21 | --Solution 22 | select avg(number) as median 23 | from 24 | (select number, sum(frequency) over(order by number) as cum_sum, 25 | ((sum(frequency) over())/2 as middle 26 | from Numbers) t1 27 | where middle between (cum_sum-frequency) and cum_sum 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Josua Antonius Naiborhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /easy/Consecutive available seats.sql: -------------------------------------------------------------------------------- 1 | -- Question 37 2 | -- Several friends at a cinema ticket office would like to reserve consecutive available seats. 3 | -- Can you help to query all the consecutive available seats order by the seat_id using the following cinema table? 4 | -- | seat_id | free | prev next 5 | -- |---------|------| 6 | -- | 1 | 1 | 1 0 7 | -- | 2 | 0 | 1 1 8 | -- | 3 | 1 | 1 1 9 | -- | 4 | 1 | 1 1 10 | -- | 5 | 1 | 1 1 11 | 12 | 13 | -- Your query should return the following result for the sample case above. 14 | 15 | 16 | -- | seat_id | 17 | -- |---------| 18 | -- | 3 | 19 | -- | 4 | 20 | -- | 5 | 21 | -- Note: 22 | -- The seat_id is an auto increment int, and free is bool ('1' means free, and '0' means occupied.). 23 | -- Consecutive available seats are more than 2(inclusive) seats consecutively available. 24 | 25 | 26 | -- Solution 27 | select seat_id 28 | from 29 | (select seat_id,free 30 | lag(free,1) over() as prev, 31 | lead(free,1) over() as next 32 | from cinema ) a 33 | a.free =True and (prev= True or next = True) 34 | order by seat_id 35 | -------------------------------------------------------------------------------- /easy/Fix Names In A Table Problem.sql: -------------------------------------------------------------------------------- 1 | -- Table Users 2 | +----------------+---------+ 3 | | Column Name | Type | 4 | +----------------+---------+ 5 | | user_id | int | 6 | | name | varchar | 7 | +----------------+---------+ 8 | -- user_id is the primary key for this table. 9 | -- This table contains the ID and the name of the user. The name consists of only lowercase and uppercase characters. 10 | 11 | -- Write an SQL query to fix the names so that only the first character is uppercase and the rest are lowercase. 12 | -- Return the result table ordered by user_id. 13 | -- The query result format is in the following example: 14 | 15 | -- Users table: 16 | +---------+-------+ 17 | | user_id | name | 18 | +---------+-------+ 19 | | 1 | aLice | 20 | | 2 | bOB | 21 | +---------+-------+ 22 | 23 | -- Result table: 24 | +---------+-------+ 25 | | user_id | name | 26 | +---------+-------+ 27 | | 1 | Alice | 28 | | 2 | Bob | 29 | +---------+-------+ 30 | 31 | -- Solution 1 32 | select user_id,initcap(name) 33 | from Users 34 | order by 1 35 | 36 | -- Solution 2 37 | 38 | select user_id, concat(upper(left(name,1)),lower(substring(name,2))) as name 39 | from Users 40 | order by 1 -------------------------------------------------------------------------------- /medium/Exchange Seats.sql: -------------------------------------------------------------------------------- 1 | -- Question 56 2 | -- Mary is a teacher in a middle school and she has a table seat storing students' names and their corresponding seat ids. 3 | 4 | -- The column id is continuous increment. 5 | 6 | 7 | -- Mary wants to change seats for the adjacent students. 8 | 9 | 10 | -- Can you write a SQL query to output the result for Mary? 11 | 12 | 13 | -- +---------+---------+ 14 | -- | id | student | 15 | -- +---------+---------+ 16 | -- | 1 | Abbot | 17 | -- | 2 | Doris | 18 | -- | 3 | Emerson | 19 | -- | 4 | Green | 20 | -- | 5 | Jeames | 21 | -- +---------+---------+ 22 | -- For the sample input, the output is: 23 | 24 | 25 | -- +---------+---------+ 26 | -- | id | student | 27 | -- +---------+---------+ 28 | -- | 1 | Doris | 29 | -- | 2 | Abbot | 30 | -- | 3 | Green | 31 | -- | 4 | Emerson | 32 | -- | 5 | Jeames | 33 | -- +---------+---------+ 34 | 35 | 36 | 37 | -- So;ution 1 38 | select row_number() over(order by case when mod(id,2)=0 then id-1 else id+1 end) as id,student 39 | from seat 40 | 41 | 42 | 43 | -- Solution 2 44 | select id, lead(student,length(student)-1) over() as student 45 | from seat 46 | -------------------------------------------------------------------------------- /easy/Employee Bonus.sql: -------------------------------------------------------------------------------- 1 | -- Question 4 2 | -- Select all employee's name and bonus whose bonus is < 1000. 3 | 4 | -- Table:Employee 5 | 6 | -- +-------+--------+-----------+--------+ 7 | -- | empId | name | supervisor| salary | 8 | -- +-------+--------+-----------+--------+ 9 | -- | 1 | John | 3 | 1000 | 10 | -- | 2 | Dan | 3 | 2000 | 11 | -- | 3 | Brad | null | 4000 | 12 | -- | 4 | Thomas | 3 | 4000 | 13 | -- +-------+--------+-----------+--------+ 14 | -- empId is the primary key column for this table. 15 | -- Table: Bonus 16 | 17 | -- +-------+-------+ 18 | -- | empId | bonus | 19 | -- +-------+-------+ 20 | -- | 2 | 500 | 21 | -- | 4 | 2000 | 22 | -- +-------+-------+ 23 | -- empId is the primary key column for this table. 24 | -- Example ouput: 25 | 26 | -- +-------+-------+ 27 | -- | name | bonus | 28 | -- +-------+-------+ 29 | -- | John | null | 30 | -- | Dan | 500 | 31 | -- | Brad | null | 32 | -- +-------+-------+ 33 | 34 | -- Solution 35 | select e.name as name, b.bonus as bonus 36 | from employee 37 | left join bonus 38 | using(empId) 39 | where b.bonus < 1000 and b.bonus is null 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /easy/Invalid Tweets.sql: -------------------------------------------------------------------------------- 1 | -- Table Tweets 2 | +----------------+---------+ 3 | | Column Name | Type | 4 | +----------------+---------+ 5 | | tweet_id | int | 6 | | content | varchar | 7 | +----------------+---------+ 8 | -- tweet_id is the primary key for this table. 9 | -- This table contains all the tweets in a social media app. 10 | 11 | -- Write an SQL query to find the IDs of the invalid tweets. 12 | -- The tweet is invalid if the number of characters used in the content of the tweet is strictly greater than 15. 13 | -- Return the result table in any order. 14 | -- The query result format is in the following example: 15 | 16 | -- Tweets table: 17 | +----------+----------------------------------+ 18 | | tweet_id | content | 19 | +----------+----------------------------------+ 20 | | 1 | Vote for Biden | 21 | | 2 | Let us make America great again! | 22 | +----------+----------------------------------+ 23 | 24 | -- Result table: 25 | +----------+ 26 | | tweet_id | 27 | +----------+ 28 | | 2 | 29 | +----------+ 30 | -- Tweet 1 has length = 14. It is a valid tweet. 31 | -- Tweet 2 has length = 32. It is an invalid tweet. 32 | 33 | -- Solution 34 | select tweet_id 35 | from tweets 36 | where length(content) > 15 -------------------------------------------------------------------------------- /easy/Find Followers Count.sql: -------------------------------------------------------------------------------- 1 | -- Table Followers 2 | +-------------+------+ 3 | | Column Name | Type | 4 | +-------------+------+ 5 | | user_id | int | 6 | | follower_id | int | 7 | +-------------+------+ 8 | -- (user_id, follower_id) is the primary key for this table. 9 | -- This table contains the IDs of a user and a follower in a social media app where the follower follows the user. 10 | 11 | -- Write an SQL query that will, for each user, return the number of followers. 12 | -- Return the result table ordered by user_id. 13 | -- The query result format is in the following example: 14 | 15 | -- Followers table: 16 | +---------+-------------+ 17 | | user_id | follower_id | 18 | +---------+-------------+ 19 | | 0 | 1 | 20 | | 1 | 0 | 21 | | 2 | 0 | 22 | | 2 | 1 | 23 | +---------+-------------+ 24 | -- Result table: 25 | +---------+----------------+ 26 | | user_id | followers_count| 27 | +---------+----------------+ 28 | | 0 | 1 | 29 | | 1 | 1 | 30 | | 2 | 2 | 31 | +---------+----------------+ 32 | -- The followers of 0 are {1} 33 | -- The followers of 1 are {0} 34 | -- The followers of 2 are {0,1} 35 | 36 | --Solution 37 | select user_id, count(distinct follower_id) as followers_count 38 | from Followers 39 | group by 1 40 | order by 1 -------------------------------------------------------------------------------- /easy/Not Boring movies.sql: -------------------------------------------------------------------------------- 1 | -- Question 6 2 | -- X city opened a new cinema, many people would like to go to this cinema. 3 | -- The cinema also gives out a poster indicating the movies’ ratings and descriptions. 4 | -- Please write a SQL query to output movies with an odd numbered ID and a description that is not 'boring'. 5 | -- Order the result by rating. 6 | 7 | 8 | 9 | -- For example, table cinema: 10 | 11 | -- +---------+-----------+--------------+-----------+ 12 | -- | id | movie | description | rating | 13 | -- +---------+-----------+--------------+-----------+ 14 | -- | 1 | War | great 3D | 8.9 | 15 | -- | 2 | Science | fiction | 8.5 | 16 | -- | 3 | irish | boring | 6.2 | 17 | -- | 4 | Ice song | Fantacy | 8.6 | 18 | -- | 5 | House card| Interesting| 9.1 | 19 | -- +---------+-----------+--------------+-----------+ 20 | -- For the example above, the output should be: 21 | -- +---------+-----------+--------------+-----------+ 22 | -- | id | movie | description | rating | 23 | -- +---------+-----------+--------------+-----------+ 24 | -- | 5 | House card| Interesting| 9.1 | 25 | -- | 1 | War | great 3D | 8.9 | 26 | -- +---------+-----------+--------------+-----------+ 27 | 28 | -- Solution 29 | Select * 30 | from cinema 31 | where mod(id,2) = 1 and description <> "boring" 32 | order by rating desc 33 | -------------------------------------------------------------------------------- /easy/Recyclable and Low Fat Products.sql: -------------------------------------------------------------------------------- 1 | -- Table Products 2 | +-------------+---------+ 3 | | Column Name | Type | 4 | +-------------+---------+ 5 | | product_id | int | 6 | | low_fats | enum | 7 | | recyclable | enum | 8 | +-------------+---------+ 9 | -- product_id is the primary key for this table. 10 | -- low_fats is an ENUM of type ('Y', 'N') where 'Y' means this product is low fat and 'N' means it is not. 11 | -- recyclable is an ENUM of types ('Y', 'N') where 'Y' means this product is recyclable and 'N' means it is not. 12 | 13 | -- Write an SQL query to find the ids of products that are both low fat and recyclable. 14 | -- Return the result table in any order. 15 | -- The query result format is in the following example: 16 | 17 | -- Products table: 18 | +-------------+----------+------------+ 19 | | product_id | low_fats | recyclable | 20 | +-------------+----------+------------+ 21 | | 0 | Y | N | 22 | | 1 | Y | Y | 23 | | 2 | N | Y | 24 | | 3 | Y | Y | 25 | | 4 | N | N | 26 | +-------------+----------+------------+ 27 | -- Result table: 28 | +-------------+ 29 | | product_id | 30 | +-------------+ 31 | | 1 | 32 | | 3 | 33 | +-------------+ 34 | --Only products 1 and 3 are both low fat and recyclable. 35 | 36 | -- Solution 37 | select product_id 38 | from products 39 | where low_fats ="Y" and recyclable ="Y" -------------------------------------------------------------------------------- /easy/Big Countries.sql: -------------------------------------------------------------------------------- 1 | -- Question 5 2 | -- There is a table World 3 | 4 | -- +-----------------+------------+------------+--------------+---------------+ 5 | -- | name | continent | area | population | gdp | 6 | -- +-----------------+------------+------------+--------------+---------------+ 7 | -- | Afghanistan | Asia | 652230 | 25500100 | 20343000 | 8 | -- | Albania | Europe | 28748 | 2831741 | 12960000 | 9 | -- | Algeria | Africa | 2381741 | 37100000 | 188681000 | 10 | -- | Andorra | Europe | 468 | 78115 | 3712000 | 11 | -- | Angola | Africa | 1246700 | 20609294 | 100990000 | 12 | -- +-----------------+------------+------------+--------------+---------------+ 13 | -- A country is big if it has an area of bigger than 3 million square km or a population of more than 25 million. 14 | 15 | -- Write a SQL solution to output big countries' name, population and area. 16 | 17 | -- For example, according to the above table, we should output: 18 | 19 | -- +--------------+-------------+--------------+ 20 | -- | name | population | area | 21 | -- +--------------+-------------+--------------+ 22 | -- | Afghanistan | 25500100 | 652230 | 23 | -- | Algeria | 37100000 | 2381741 | 24 | -- +--------------+-------------+--------------+ 25 | 26 | 27 | -- Solution 28 | Select name, population, area 29 | from world 30 | where population > 25000000 OR area>3000000 -------------------------------------------------------------------------------- /easy/Actors who cooperated with Directors atleast three times.sql: -------------------------------------------------------------------------------- 1 | -- Question 21 2 | -- Table: ActorDirector 3 | 4 | -- +-------------+---------+ 5 | -- | Column Name | Type | 6 | -- +-------------+---------+ 7 | -- | actor_id | int | 8 | -- | director_id | int | 9 | -- | timestamp | int | 10 | -- +-------------+---------+ 11 | -- timestamp is the primary key column for this table. 12 | 13 | 14 | -- Write a SQL query for a report that provides the pairs (actor_id, director_id) where the actor have cooperated with the director at least 3 times. 15 | 16 | -- Example: 17 | 18 | -- ActorDirector table: 19 | -- +-------------+-------------+-------------+ 20 | -- | actor_id | director_id | timestamp | 21 | -- +-------------+-------------+-------------+ 22 | -- | 1 | 1 | 0 | 23 | -- | 1 | 1 | 1 | 24 | -- | 1 | 1 | 2 | 25 | -- | 1 | 2 | 3 | 26 | -- | 1 | 2 | 4 | 27 | -- | 2 | 1 | 5 | 28 | -- | 2 | 1 | 6 | 29 | -- +-------------+-------------+-------------+ 30 | 31 | -- Result table: 32 | -- +-------------+-------------+ 33 | -- | actor_id | director_id | 34 | -- +-------------+-------------+ 35 | -- | 1 | 1 | 36 | -- +-------------+-------------+ 37 | -- The only pair is (1, 1) where they cooperated exactly 3 times. 38 | 39 | -- Solution 40 | select actor_id, director_id 41 | from actordirector 42 | group by 1, 2 43 | having count(*)>=3 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Most appearance Database Questions in FAANG Companies 2 | This repository is used to practices our SQL using postgreSQL by questions of FAANG Companies. 3 | 4 | ## The Motivations 5 | I try implementing my Postgresql skills to improve and optimize query better and i believe the true education is when you can implement what you learn or **simply learn by doing**. 6 | You can access the questions in leetcode [database section](https://leetcode.com/problemset/database/) 7 | 8 | I included some resources to brush up on our technique in postgresql through a few sites 9 | # List of Resources to learn PostgreSQL 10 | 1. [SQL Interview Prep Doc](https://docs.google.com/document/d/1Bqdx2xwodHPdiW2w3yzjB9CNtWzGD2UP/edit) 11 | 2. [PostgreExercises](https://pgexercises.com/) 12 | 3. [The Best Medium-Hard Data Analyst SQL Interview Questions](https://quip.com/2gwZArKuWk7W) 13 | 4. [Optimization Query](https://media-exp1.licdn.com/dms/document/C4E1FAQFp-9PKAJIe9g/feedshare-document-pdf-analyzed/0/1632384814712?e=1632506400&v=beta&t=IaildObewotNigJsvcRgvwZF6rdkf1RKVfUv77O7CIM) 14 | 5. [Data School](https://dataschool.com/books/) 15 | 16 | I also included some financial statements to brush up on our knowledge of FAANG companies in order to know some metrics to business cases in FAANG companies. 17 | 1. [Amazon](https://github.com/naiborhujosua/faang_sql_questions_postgresql/blob/main/investorsrelations/AMZN-Q2-2021-Earnings-Release.pdf) 18 | 2. [Facebook](https://github.com/naiborhujosua/faang_sql_questions_postgresql/blob/main/investorsrelations/Facebook-Reports-Third-Quarter-2020-Results-2020.pdf) 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /medium/ Find the Missing IDs.sql: -------------------------------------------------------------------------------- 1 | -- Table: Customers 2 | +---------------+---------+ 3 | | Column Name | Type | 4 | +---------------+---------+ 5 | | customer_id | int | 6 | | customer_name | varchar | 7 | +---------------+---------+ 8 | --customer_id is the primary key for this table. 9 | --Each row of this table contains the name and the id customer. 10 | 11 | --Write an SQL query to find the missing customer IDs. The missing IDs are ones that are not in the Customers table but are in 12 | --the range between 1 and the maximum customer_id present in the table. 13 | --Notice that the maximum customer_id will not exceed 100. 14 | --Return the result table ordered by ids in ascending order. 15 | --The query result format is in the following example. 16 | 17 | 18 | -- Customers table: 19 | +-------------+---------------+ 20 | | customer_id | customer_name | 21 | +-------------+---------------+ 22 | | 1 | Alice | 23 | | 4 | Bob | 24 | | 5 | Charlie | 25 | +-------------+---------------+ 26 | --Result table: 27 | +-----+ 28 | | ids | 29 | +-----+ 30 | | 2 | 31 | | 3 | 32 | +-----+ 33 | --The maximum customer_id present in the table is 5, so in the range [1,5], IDs 2 and 3 are missing from the table. 34 | 35 | --Solution 36 | 37 | with recursive cte (ids) as 38 | ( 39 | select 1 as ids 40 | 41 | union all 42 | 43 | select ids + 1 44 | from cte 45 | where ids < (select max(customer_id) from Customers) 46 | ) 47 | 48 | select ids 49 | from cte 50 | where ids not in (select customer_id from Customers) 51 | order by ids 52 | -------------------------------------------------------------------------------- /easy/patients with conditions.sql: -------------------------------------------------------------------------------- 1 | -- Table patients 2 | +--------------+---------+ 3 | | Column Name | Type | 4 | +--------------+---------+ 5 | | patient_id | int | 6 | | patient_name | varchar | 7 | | conditions | varchar | 8 | +--------------+---------+ 9 | -- patient_id is the primary key for this table. 10 | -- 'conditions' contains 0 or more code separated by spaces. 11 | -- This table contains information of the patients in the hospital. 12 | 13 | -- Write an SQL query to report the patient_id, patient_name all conditions of patients who have Type I Diabetes. Type I Diabetes always starts with DIAB1 prefix 14 | 15 | -- Return the result table in any order. 16 | 17 | -- Patients 18 | +------------+--------------+--------------+ 19 | | patient_id | patient_name | conditions | 20 | +------------+--------------+--------------+ 21 | | 1 | Daniel | YFEV COUGH | 22 | | 2 | Alice | | 23 | | 3 | Bob | DIAB100 MYOP | 24 | | 4 | George | ACNE DIAB100 | 25 | | 5 | Alain | DIAB201 | 26 | +------------+--------------+--------------+ 27 | 28 | -- Result table: 29 | +------------+--------------+--------------+ 30 | | patient_id | patient_name | conditions | 31 | +------------+--------------+--------------+ 32 | | 3 | Bob | DIAB100 MYOP | 33 | | 4 | George | ACNE DIAB100 | 34 | +------------+--------------+--------------+ 35 | Bob and George both have a condition that starts with DIAB1. 36 | 37 | select patient_id,patient_name,condition 38 | from patients 39 | where condition like "%DIAB1%" -------------------------------------------------------------------------------- /easy/Find Customers With Positive Revenue this Year.sql: -------------------------------------------------------------------------------- 1 | -- Table Customers 2 | 3 | +--------------+------+ 4 | | Column Name | Type | 5 | +--------------+------+ 6 | | customer_id | int | 7 | | year | int | 8 | | revenue | int | 9 | +--------------+------+ 10 | -- (customer_id, year) is the primary key for this table. 11 | -- This table contains the customer ID and the revenue of customers in different years. 12 | -- Note that this revenue can be negative. 13 | 14 | -- Write an SQL query to report the customers with postive revenue in the year 2021. 15 | -- Return the result table in any order. 16 | -- The query result format is in the following example: 17 | 18 | -- Customers 19 | +-------------+------+---------+ 20 | | customer_id | year | revenue | 21 | +-------------+------+---------+ 22 | | 1 | 2018 | 50 | 23 | | 1 | 2021 | 30 | 24 | | 1 | 2020 | 70 | 25 | | 2 | 2021 | -50 | 26 | | 3 | 2018 | 10 | 27 | | 3 | 2016 | 50 | 28 | | 4 | 2021 | 20 | 29 | +-------------+------+---------+ 30 | 31 | -- Result table: 32 | +-------------+ 33 | | customer_id | 34 | +-------------+ 35 | | 1 | 36 | | 4 | 37 | +-------------+ 38 | 39 | -- Customer 1 has revenue equal to 30 in year 2021. 40 | -- Customer 2 has revenue equal to -50 in year 2021. 41 | -- Customer 3 has no revenue in year 2021. 42 | -- Customer 4 has revenue equal to 20 in year 2021. 43 | -- Thus only customers 1 and 4 have postive revenue in year 2021. 44 | 45 | --Solution 46 | select customer_id 47 | from Customers 48 | where year =2021 49 | group by customer_id, year 50 | having sum(revenue) > 0 51 | -------------------------------------------------------------------------------- /medium/Find the start and end number of continuous ranges.sql: -------------------------------------------------------------------------------- 1 | -- Question 80 2 | -- Table: Logs 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | log_id | int | 8 | -- +---------------+---------+ 9 | -- id is the primary key for this table. 10 | -- Each row of this table contains the ID in a log Table. 11 | 12 | -- Since some IDs have been removed from Logs. Write an SQL query to find the start and end number of continuous ranges in table Logs. 13 | 14 | -- Order the result table by start_id. 15 | 16 | -- The query result format is in the following example: 17 | 18 | -- Logs table: 19 | -- +------------+ 20 | -- | log_id | 21 | -- +------------+ rk 22 | -- | 1 | 1 0 23 | -- | 2 | 2 0 24 | -- | 3 | 3 0 25 | -- | 7 | 4 3 26 | -- | 8 | 5 3 27 | -- | 10 | 6 4 28 | -- +------------+ 29 | 30 | -- Result table: 31 | -- +------------+--------------+ 32 | -- | start_id | end_id | 33 | -- +------------+--------------+ 34 | -- | 1 | 3 | 35 | -- | 7 | 8 | 36 | -- | 10 | 10 | 37 | -- +------------+--------------+ 38 | -- The result table should contain all ranges in table Logs. 39 | -- From 1 to 3 is contained in the table. 40 | -- From 4 to 6 is missing in the table 41 | -- From 7 to 8 is contained in the table. 42 | -- Number 9 is missing in the table. 43 | -- Number 10 is contained in the table. 44 | 45 | -- Solution 46 | select min(log_id) as start_id, max(log_id) as end_id 47 | from( 48 | select log_id, log_id-row_number() over (order by log_id) as rk 49 | from logs) a 50 | group by rk -------------------------------------------------------------------------------- /easy/Game Play Analysis 1.sql: -------------------------------------------------------------------------------- 1 | -- Question 3 2 | -- Table: Activity 3 | 4 | -- +--------------+---------+ 5 | -- | Column Name | Type | 6 | -- +--------------+---------+ 7 | -- | player_id | int | 8 | -- | device_id | int | 9 | -- | event_date | date | 10 | -- | games_played | int | 11 | -- +--------------+---------+ 12 | -- (player_id, event_date) is the primary key of this table. 13 | -- This table shows the activity of players of some game. 14 | -- Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device. 15 | 16 | 17 | -- Write an SQL query that reports the first login date for each player. 18 | 19 | -- The query result format is in the following example: 20 | 21 | -- Activity table: 22 | -- +-----------+-----------+------------+--------------+ 23 | -- | player_id | device_id | event_date | games_played | 24 | -- +-----------+-----------+------------+--------------+ 25 | -- | 1 | 2 | 2016-03-01 | 5 | 26 | -- | 1 | 2 | 2016-05-02 | 6 | 27 | -- | 2 | 3 | 2017-06-25 | 1 | 28 | -- | 3 | 1 | 2016-03-02 | 0 | 29 | -- | 3 | 4 | 2018-07-03 | 5 | 30 | -- +-----------+-----------+------------+--------------+ 31 | 32 | -- Result table: 33 | -- +-----------+-------------+ 34 | -- | player_id | first_login | 35 | -- +-----------+-------------+ 36 | -- | 1 | 2016-03-01 | 37 | -- | 2 | 2017-06-25 | 38 | -- | 3 | 2016-03-02 | 39 | -- +-----------+-------------+ 40 | 41 | -- Solution 42 | Select player_id,min(event_date) as first_login 43 | from activity 44 | group by player_id 45 | -------------------------------------------------------------------------------- /easy/Article views.sql: -------------------------------------------------------------------------------- 1 | -- Question 42 2 | -- Table: Views 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | article_id | int | 8 | -- | author_id | int | 9 | -- | viewer_id | int | 10 | -- | view_date | date | 11 | -- +---------------+---------+ 12 | -- There is no primary key for this table, it may have duplicate rows. 13 | -- Each row of this table indicates that some viewer viewed an article (written by some author) on some date. 14 | -- Note that equal author_id and viewer_id indicate the same person. 15 | 16 | 17 | -- Write an SQL query to find all the authors that viewed at least one of their own articles, sorted in ascending order by their id. 18 | 19 | -- The query result format is in the following example: 20 | 21 | -- Views table: 22 | -- +------------+-----------+-----------+------------+ 23 | -- | article_id | author_id | viewer_id | view_date | 24 | -- +------------+-----------+-----------+------------+ 25 | -- | 1 | 3 | 5 | 2019-08-01 | 26 | -- | 1 | 3 | 6 | 2019-08-02 | 27 | -- | 2 | 7 | 7 | 2019-08-01 | 28 | -- | 2 | 7 | 6 | 2019-08-02 | 29 | -- | 4 | 7 | 1 | 2019-07-22 | 30 | -- | 3 | 4 | 4 | 2019-07-21 | 31 | -- | 3 | 4 | 4 | 2019-07-21 | 32 | -- +------------+-----------+-----------+------------+ 33 | 34 | -- Result table: 35 | -- +------+ 36 | -- | id | 37 | -- +------+ 38 | -- | 4 | 39 | -- | 7 | 40 | -- +------+ 41 | 42 | 43 | -- Solution 44 | select distinct author_id as id 45 | from views 46 | where author_id = viewer_id 47 | order by author_id 48 | 49 | -------------------------------------------------------------------------------- /easy/Game play analysis 2.sql: -------------------------------------------------------------------------------- 1 | -- Question 9 2 | -- Table: Activity 3 | 4 | -- +--------------+---------+ 5 | -- | Column Name | Type | 6 | -- +--------------+---------+ 7 | -- | player_id | int | 8 | -- | device_id | int | 9 | -- | event_date | date | 10 | -- | games_played | int | 11 | -- +--------------+---------+ 12 | -- (player_id, event_date) is the primary key of this table. 13 | -- This table shows the activity of players of some game. 14 | -- Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device. 15 | 16 | -- Write a SQL query that reports the device that is first logged in for each player. 17 | 18 | -- The query result format is in the following example: 19 | 20 | -- Activity table: 21 | -- +-----------+-----------+------------+--------------+ 22 | -- | player_id | device_id | event_date | games_played | 23 | -- +-----------+-----------+------------+--------------+ 24 | -- | 1 | 2 | 2016-03-01 | 5 | 25 | -- | 1 | 2 | 2016-05-02 | 6 | 26 | -- | 2 | 3 | 2017-06-25 | 1 | 27 | -- | 3 | 1 | 2016-03-02 | 0 | 28 | -- | 3 | 4 | 2018-07-03 | 5 | 29 | -- +-----------+-----------+------------+--------------+ 30 | 31 | -- Result table: 32 | -- +-----------+-----------+ 33 | -- | player_id | device_id | 34 | -- +-----------+-----------+ 35 | -- | 1 | 2 | 36 | -- | 2 | 3 | 37 | -- | 3 | 1 | 38 | -- +-----------+-----------+ 39 | 40 | -- Solution 41 | select a.player_id,a.device_id 42 | from( 43 | select player_id,device_id,min(event_date) 44 | from activity 45 | group by 1) a 46 | 47 | 48 | -------------------------------------------------------------------------------- /easy/Find the team size.sql: -------------------------------------------------------------------------------- 1 | -- Question 47 2 | -- Table: Employee 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | employee_id | int | 8 | -- | team_id | int | 9 | -- +---------------+---------+ 10 | -- employee_id is the primary key for this table. 11 | -- Each row of this table contains the ID of each employee and their respective team. 12 | -- Write an SQL query to find the team size of each of the employees. 13 | 14 | -- Return result table in any order. 15 | 16 | -- The query result format is in the following example: 17 | 18 | -- Employee Table: 19 | -- +-------------+------------+ 20 | -- | employee_id | team_id | 21 | -- +-------------+------------+ 22 | -- | 1 | 8 | 23 | -- | 2 | 8 | 24 | -- | 3 | 8 | 25 | -- | 4 | 7 | 26 | -- | 5 | 9 | 27 | -- | 6 | 9 | 28 | -- +-------------+------------+ 29 | -- Result table: 30 | -- +-------------+------------+ 31 | -- | employee_id | team_size | 32 | -- +-------------+------------+ 33 | -- | 1 | 3 | 34 | -- | 2 | 3 | 35 | -- | 3 | 3 | 36 | -- | 4 | 1 | 37 | -- | 5 | 2 | 38 | -- | 6 | 2 | 39 | -- +-------------+------------+ 40 | -- Employees with Id 1,2,3 are part of a team with team_id = 8. 41 | -- Employees with Id 4 is part of a team with team_id = 7. 42 | -- Employees with Id 5,6 are part of a team with team_id = 9. 43 | 44 | 45 | -- Solution 46 | select employee_id,a.team_size 47 | from employee e 48 | join 49 | (select team_id,count(team_id) as team_size 50 | from Employee 51 | group by team_id) a 52 | using(team_id) 53 | -------------------------------------------------------------------------------- /easy/Calculate Special Bonus.sql: -------------------------------------------------------------------------------- 1 | Table Employees 2 | 3 | +-------------+---------+ 4 | | Column Name | Type | 5 | +-------------+---------+ 6 | | employee_id | int | 7 | | name | varchar | 8 | | salary | int | 9 | +-------------+---------+ 10 | -- employee_id is the primary key for this table. 11 | -- Each row of this table indicates the employee ID, employee name, and salary. 12 | 13 | -- Write an SQL query to calculate the bonus of each employee. The bonus of an employee is 100% of their salary if the ID of the employee is an odd number and the employee name does not start with the character 'M'. The bonus of an employee is 0 otherwise. 14 | -- Return the result table ordered by employee_id. 15 | -- The query result format is in the following example: 16 | 17 | -- Employees table: 18 | +-------------+---------+--------+ 19 | | employee_id | name | salary | 20 | +-------------+---------+--------+ 21 | | 2 | Meir | 3000 | 22 | | 3 | Michael | 3800 | 23 | | 7 | Addilyn | 7400 | 24 | | 8 | Juan | 6100 | 25 | | 9 | Kannon | 7700 | 26 | +-------------+---------+--------+ 27 | 28 | -- Result table: 29 | +-------------+-------+ 30 | | employee_id | bonus | 31 | +-------------+-------+ 32 | | 2 | 0 | 33 | | 3 | 0 | 34 | | 7 | 7400 | 35 | | 8 | 0 | 36 | | 9 | 7700 | 37 | +-------------+-------+ 38 | 39 | -- The employees with IDs 2 and 8 get 0 bonus because they have an even employee_id. 40 | -- The employee with ID 3 gets 0 bonus because their name starts with 'M'. 41 | -- The rest of the employees get a 100% bonus. 42 | 43 | --Solution 44 | select employee_id, 45 | case when mod(salary,2) <> 0 and name not like "M%" then salary 46 | else 0 end as bonus 47 | from employees 48 | -------------------------------------------------------------------------------- /easy/Product's Price For Each Store Problem.sql: -------------------------------------------------------------------------------- 1 | -- Table Products 2 | 3 | +-------------+---------+ 4 | | Column Name | Type | 5 | +-------------+---------+ 6 | | product_id | int | 7 | | store | enum | 8 | | price | int | 9 | +-------------+---------+ 10 | -- (product_id,store) is the primary key for this table. 11 | -- store is an ENUM of type ('store1', 'store2', 'store3') where each represents the store this product is available at. 12 | -- price is the price of the product at this store. 13 | 14 | -- Write an SQL query to find the price of each product in each store. 15 | -- Return the result table in any order. 16 | -- The query result format is in the following example: 17 | 18 | Products table: 19 | +-------------+--------+-------+ 20 | | product_id | store | price | 21 | +-------------+--------+-------+ 22 | | 0 | store1 | 95 | 23 | | 0 | store3 | 105 | 24 | | 0 | store2 | 100 | 25 | | 1 | store1 | 70 | 26 | | 1 | store3 | 80 | 27 | +-------------+--------+-------+ 28 | Result table: 29 | +-------------+--------+--------+--------+ 30 | | product_id | store1 | store2 | store3 | 31 | +-------------+--------+--------+--------+ 32 | | 0 | 95 | 100 | 105 | 33 | | 1 | 70 | null | 80 | 34 | +-------------+--------+--------+--------+ 35 | -- Product 0 price's are 95 for store1, 100 for store2 and, 105 for store3. 36 | -- Product 1 price's are 70 for store1, 80 for store3 and, it's not sold in store2. 37 | 38 | -- Solution 39 | select product_id, 40 | select product_id, 41 | sum(case when store="store1" then price else null end as "store1"), 42 | sum(case when store="store2" then price else null end as "store2"), 43 | sum(case when store="store3" then price else null end as "store3") 44 | from products 45 | group by 1 -------------------------------------------------------------------------------- /easy/Customer placing the largest number of orders .sql: -------------------------------------------------------------------------------- 1 | -- Question 8 2 | -- Query the customer_number from the orders table for the customer who has placed the largest number of orders. 3 | 4 | -- It is guaranteed that exactly one customer will have placed more orders than any other customer. 5 | 6 | -- The orders table is defined as follows: 7 | 8 | -- | Column | Type | 9 | -- |-------------------|-----------| 10 | -- | order_number (PK) | int | 11 | -- | customer_number | int | 12 | -- | order_date | date | 13 | -- | required_date | date | 14 | -- | shipped_date | date | 15 | -- | status | char(15) | 16 | -- | comment | char(200) | 17 | -- Sample Input 18 | 19 | -- | order_number | customer_number | order_date | required_date | shipped_date | status | comment | 20 | -- |--------------|-----------------|------------|---------------|--------------|--------|---------| 21 | -- | 1 | 1 | 2017-04-09 | 2017-04-13 | 2017-04-12 | Closed | | 22 | -- | 2 | 2 | 2017-04-15 | 2017-04-20 | 2017-04-18 | Closed | | 23 | -- | 3 | 3 | 2017-04-16 | 2017-04-25 | 2017-04-20 | Closed | | 24 | -- | 4 | 3 | 2017-04-18 | 2017-04-28 | 2017-04-25 | Closed | | 25 | -- Sample Output 26 | 27 | -- | customer_number | 28 | -- |-----------------| 29 | -- | 3 | 30 | -- Explanation 31 | 32 | -- The customer with number '3' has two orders, 33 | -- which is greater than either customer '1' or '2' because each of them only has one order. 34 | -- So the result is customer_number '3'. 35 | 36 | -- Solution 37 | Select customer_number 38 | from orders 39 | group by customer_number 40 | order by count(*) desc 41 | limit 1 42 | 43 | 44 | -------------------------------------------------------------------------------- /medium/Friend Requests 2.sql: -------------------------------------------------------------------------------- 1 | -- Question 60 2 | -- In social network like Facebook or Twitter, people send friend requests and accept others' requests as well. 3 | 4 | -- Table request_accepted 5 | 6 | -- +--------------+-------------+------------+ 7 | -- | requester_id | accepter_id | accept_date| 8 | -- |--------------|-------------|------------| 9 | -- | 1 | 2 | 2016_06-03 | 10 | -- | 1 | 3 | 2016-06-08 | 11 | -- | 2 | 3 | 2016-06-08 | 12 | -- | 3 | 4 | 2016-06-09 | 13 | -- +--------------+-------------+------------+ 14 | -- This table holds the data of friend acceptance, while requester_id and accepter_id both are the id of a person. 15 | 16 | 17 | -- Write a query to find the the people who has most friends and the most friends number under the following rules: 18 | 19 | -- It is guaranteed there is only 1 people having the most friends. 20 | -- The friend request could only been accepted once, which mean there is no multiple records with the same requester_id and accepter_id value. 21 | -- For the sample data above, the result is: 22 | 23 | -- Result table: 24 | -- +------+------+ 25 | -- | id | num | 26 | -- |------|------| 27 | -- | 3 | 3 | 28 | -- +------+------+ 29 | -- The person with id '3' is a friend of people '1', '2' and '4', so he has 3 friends in total, which is the most number than any others. 30 | 31 | ids 32 | 1 33 | 1 34 | 2 35 | 3 36 | 2 37 | 3 38 | 3 39 | 4 40 | ids 41 | 1 2 42 | 2 2 43 | 3 3 44 | 4 1 45 | 46 | select b.requester_id as id,count(*) as num 47 | (select a.requester_id as id,count(a.requester_id) as num 48 | from 49 | (select requester_id,count(*) as total_request_id 50 | from request_accepted 51 | union all 52 | select accepter_id,count(*) as total_accepted_id 53 | from request_accepted) a 54 | group by 1 ) b 55 | order by num desc 56 | limit 1 57 | 58 | -------------------------------------------------------------------------------- /medium/Article Views 2.sql: -------------------------------------------------------------------------------- 1 | -- Question 81 2 | -- Table: Views 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | article_id | int | 8 | -- | author_id | int | 9 | -- | viewer_id | int | 10 | -- | view_date | date | 11 | -- +---------------+---------+ 12 | -- There is no primary key for this table, it may have duplicate rows. 13 | -- Each row of this table indicates that some viewer viewed an article (written by some author) on some date. 14 | -- Note that equal author_id and viewer_id indicate the same person. 15 | 16 | 17 | -- Write an SQL query to find all the people who viewed more than one article on the same date, sorted in ascending order by their id. 18 | 19 | -- The query result format is in the following example: 20 | 21 | -- Views table: 22 | -- +------------+-----------+-----------+------------+ 23 | -- | article_id | author_id | viewer_id | view_date | 24 | -- +------------+-----------+-----------+------------+ 25 | -- | 1 | 3 | 5 | 2019-08-01 | 26 | -- | 3 | 4 | 5 | 2019-08-01 | 27 | -- | 1 | 3 | 6 | 2019-08-02 | 28 | -- | 2 | 7 | 7 | 2019-08-01 | 29 | -- | 2 | 7 | 6 | 2019-08-02 | 30 | -- | 4 | 7 | 1 | 2019-07-22 | 31 | -- | 3 | 4 | 4 | 2019-07-21 | 32 | -- | 3 | 4 | 4 | 2019-07-21 | 33 | -- +------------+-----------+-----------+------------+ 34 | 35 | -- Result table: 36 | -- +------+ 37 | -- | id | 38 | -- +------+ 39 | -- | 5 | 40 | -- | 6 | 41 | -- +------+ 42 | 43 | 44 | -- Solution 45 | select distinct viewer_id as id,count(distinct article_id) as viewer_cnt 46 | from views 47 | group by viewer_id,view_date 48 | having count(distinct article_id) > 1 49 | order by viewer_id 50 | -------------------------------------------------------------------------------- /easy/Project Employees 2.sql: -------------------------------------------------------------------------------- 1 | -- Question 28 2 | -- Table: Project 3 | 4 | -- +-------------+---------+ 5 | -- | Column Name | Type | 6 | -- +-------------+---------+ 7 | -- | project_id | int | 8 | -- | employee_id | int | 9 | -- +-------------+---------+ 10 | -- (project_id, employee_id) is the primary key of this table. 11 | -- employee_id is a foreign key to Employee table. 12 | -- Table: Employee 13 | 14 | -- +------------------+---------+ 15 | -- | Column Name | Type | 16 | -- +------------------+---------+ 17 | -- | employee_id | int | 18 | -- | name | varchar | 19 | -- | experience_years | int | 20 | -- +------------------+---------+ 21 | -- employee_id is the primary key of this table. 22 | 23 | 24 | -- Write an SQL query that reports all the projects that have the most employees. 25 | 26 | -- The query result format is in the following example: 27 | 28 | -- Project table: 29 | -- +-------------+-------------+ 30 | -- | project_id | employee_id | 31 | -- +-------------+-------------+ 32 | -- | 1 | 1 | 33 | -- | 1 | 2 | 34 | -- | 1 | 3 | 35 | -- | 2 | 1 | 36 | -- | 2 | 4 | 37 | -- +-------------+-------------+ 38 | 39 | -- Employee table: 40 | -- +-------------+--------+------------------+ 41 | -- | employee_id | name | experience_years | 42 | -- +-------------+--------+------------------+ 43 | -- | 1 | Khaled | 3 | 44 | -- | 2 | Ali | 2 | 45 | -- | 3 | John | 1 | 46 | -- | 4 | Doe | 2 | 47 | -- +-------------+--------+------------------+ 48 | 49 | -- Result table: 50 | -- +-------------+ 51 | -- | project_id | 52 | -- +-------------+ 53 | -- | 1 | 54 | -- +-------------+ 55 | -- The first project has 3 employees while the second one has 2. 56 | 57 | 58 | -- Solution 59 | select p.project_id 60 | from project p 61 | inner join Employee e 62 | on e.employee_id = p.employee_id 63 | group by p.project_id 64 | order by count(e.employee_id) desc 65 | limit 1 66 | -------------------------------------------------------------------------------- /easy/Rearrange Products Table.sql: -------------------------------------------------------------------------------- 1 | -- Table Products 2 | +-------------+---------+ 3 | | Column Name | Type | 4 | +-------------+---------+ 5 | | product_id | int | 6 | | store1 | int | 7 | | store2 | int | 8 | | store3 | int | 9 | +-------------+---------+ 10 | 11 | -- product_id is the primary key for this table. 12 | -- Each row in this table indicates the product's price in 3 different stores: store1, store2, and store3. 13 | -- If the product is not available in a store, the price will be null in that store's column. 14 | 15 | -- Write an SQL query to rearrange the Products table so that each row has (product_id, store, price). If a product is not available in a store, do not include a row with that product_id and store combination in the result table. 16 | -- Return the result table in any order. 17 | -- The query result format is in the following example: 18 | 19 | -- Products table: 20 | +------------+--------+--------+--------+ 21 | | product_id | store1 | store2 | store3 | 22 | +------------+--------+--------+--------+ 23 | | 0 | 95 | 100 | 105 | 24 | | 1 | 70 | null | 80 | 25 | +------------+--------+--------+--------+ 26 | 27 | -- Result table: 28 | +------------+--------+-------+ 29 | | product_id | store | price | 30 | +------------+--------+-------+ 31 | | 0 | store1 | 95 | 32 | | 0 | store2 | 100 | 33 | | 0 | store3 | 105 | 34 | | 1 | store1 | 70 | 35 | | 1 | store3 | 80 | 36 | +------------+--------+-------+ 37 | 38 | -- Product 0 is available in all three stores with prices 95, 100, and 105 respectively. 39 | -- Product 1 is available in store1 with price 70 and store3 with price 80. The product is not available in store2. 40 | 41 | 42 | -- Solution 43 | select product_id, "store1" as store, store1 as price 44 | from products 45 | where store1 is not null 46 | union 47 | select product_id, "store2" as store, store2 as price 48 | from products 49 | where store2 is not null 50 | union 51 | select product_id, "store3" as store, store3 as price 52 | from products 53 | where store3 is not null -------------------------------------------------------------------------------- /medium/Get highest answer rate question.sql: -------------------------------------------------------------------------------- 1 | -- Question 86 2 | -- Get the highest answer rate question from a table survey_log with these columns: id, action, question_id, answer_id, q_num, timestamp. 3 | 4 | -- id means user id; action has these kind of values: "show", "answer", "skip"; answer_id is not null when action column is "answer", 5 | -- while is null for "show" and "skip"; q_num is the numeral order of the question in current session. 6 | 7 | -- Write a sql query to identify the question which has the highest answer rate. 8 | 9 | -- Example: 10 | 11 | -- Input: 12 | -- +------+-----------+--------------+------------+-----------+------------+ 13 | -- | id | action | question_id | answer_id | q_num | timestamp | 14 | -- +------+-----------+--------------+------------+-----------+------------+ 15 | -- | 5 | show | 285 | null | 1 | 123 | 16 | -- | 5 | answer | 285 | 124124 | 1 | 124 | 17 | -- | 5 | show | 369 | null | 2 | 125 | 18 | -- | 5 | skip | 369 | null | 2 | 126 | 19 | -- +------+-----------+--------------+------------+-----------+------------+ 20 | -- Output: 21 | -- +-------------+ 22 | -- | survey_log | 23 | -- +-------------+ 24 | -- | 285 | 25 | -- +-------------+ 26 | -- Explanation: 27 | -- question 285 has answer rate 1/1, while question 369 has 0/1 answer rate, so output 285. 28 | 29 | 30 | -- Note: The highest answer rate meaning is: answer number's ratio in show number in the same question. 31 | 32 | -- Solution 33 | with rates as ( 34 | select a.question_id as question_id, b.answer/a.show as rate 35 | (select question_id,coalesce(count(*),0) as show 36 | from survey_log 37 | where action <> "answer" 38 | group by question_id) a 39 | join 40 | (select question_id,coalesce(count(*),0) as answer 41 | from survey_log 42 | where answer ="answer" 43 | group by question_id) b 44 | on b.question_id = a.question_id ) 45 | 46 | select t.question_id 47 | from 48 | (select question_id, row_number() over(order by rate desc) as rk 49 | from rates ) t 50 | where t.rk = 1 51 | -------------------------------------------------------------------------------- /easy/Product Sales Analysis 1.sql: -------------------------------------------------------------------------------- 1 | -- Question 30 2 | -- Table: Sales 3 | 4 | -- +-------------+-------+ 5 | -- | Column Name | Type | 6 | -- +-------------+-------+ 7 | -- | sale_id | int | 8 | -- | product_id | int | 9 | -- | year | int | 10 | -- | quantity | int | 11 | -- | price | int | 12 | -- +-------------+-------+ 13 | -- (sale_id, year) is the primary key of this table. 14 | -- product_id is a foreign key to Product table. 15 | -- Note that the price is per unit. 16 | -- Table: Product 17 | 18 | -- +--------------+---------+ 19 | -- | Column Name | Type | 20 | -- +--------------+---------+ 21 | -- | product_id | int | 22 | -- | product_name | varchar | 23 | -- +--------------+---------+ 24 | -- product_id is the primary key of this table. 25 | 26 | 27 | -- Write an SQL query that reports all product names of the products in the Sales table along with their selling year and price. 28 | 29 | -- For example: 30 | 31 | -- Sales table: 32 | -- +---------+------------+------+----------+-------+ 33 | -- | sale_id | product_id | year | quantity | price | 34 | -- +---------+------------+------+----------+-------+ 35 | -- | 1 | 100 | 2008 | 10 | 5000 | 36 | -- | 2 | 100 | 2009 | 12 | 5000 | 37 | -- | 7 | 200 | 2011 | 15 | 9000 | 38 | -- +---------+------------+------+----------+-------+ 39 | 40 | -- Product table: 41 | -- +------------+--------------+ 42 | -- | product_id | product_name | 43 | -- +------------+--------------+ 44 | -- | 100 | Nokia | 45 | -- | 200 | Apple | 46 | -- | 300 | Samsung | 47 | -- +------------+--------------+ 48 | 49 | -- Result table: 50 | -- +--------------+-------+-------+ 51 | -- | product_name | year | price | 52 | -- +--------------+-------+-------+ 53 | -- | Nokia | 2008 | 5000 | 54 | -- | Nokia | 2009 | 5000 | 55 | -- | Apple | 2011 | 9000 | 56 | -- +--------------+-------+-------+ 57 | 58 | -- Solution 59 | Select p.product_name as product_name,s.year as year, s.price as price 60 | from sales s 61 | join product p 62 | on p.product_id = s.product_id 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /easy/Product Sales Analysis 2.sql: -------------------------------------------------------------------------------- 1 | -- Question 29 2 | -- Table: Sales 3 | 4 | -- +-------------+-------+ 5 | -- | Column Name | Type | 6 | -- +-------------+-------+ 7 | -- | sale_id | int | 8 | -- | product_id | int | 9 | -- | year | int | 10 | -- | quantity | int | 11 | -- | price | int | 12 | -- +-------------+-------+ 13 | -- sale_id is the primary key of this table. 14 | -- product_id is a foreign key to Product table. 15 | -- Note that the price is per unit. 16 | -- Table: Product 17 | 18 | -- +--------------+---------+ 19 | -- | Column Name | Type | 20 | -- +--------------+---------+ 21 | -- | product_id | int | 22 | -- | product_name | varchar | 23 | -- +--------------+---------+ 24 | -- product_id is the primary key of this table. 25 | 26 | 27 | -- Write an SQL query that reports the total quantity sold for every product id. 28 | 29 | -- The query result format is in the following example: 30 | 31 | -- Sales table: 32 | -- +---------+------------+------+----------+-------+ 33 | -- | sale_id | product_id | year | quantity | price | 34 | -- +---------+------------+------+----------+-------+ 35 | -- | 1 | 100 | 2008 | 10 | 5000 | 36 | -- | 2 | 100 | 2009 | 12 | 5000 | 37 | -- | 7 | 200 | 2011 | 15 | 9000 | 38 | -- +---------+------------+------+----------+-------+ 39 | 40 | -- Product table: 41 | -- +------------+--------------+ 42 | -- | product_id | product_name | 43 | -- +------------+--------------+ 44 | -- | 100 | Nokia | 45 | -- | 200 | Apple | 46 | -- | 300 | Samsung | 47 | -- +------------+--------------+ 48 | 49 | -- Result table: 50 | -- +--------------+----------------+ 51 | -- | product_id | total_quantity | 52 | -- +--------------+----------------+ 53 | -- | 100 | 22 | 54 | -- | 200 | 15 | 55 | -- +--------------+----------------+ 56 | 57 | 58 | 59 | 60 | -- Solution 61 | Select s.product_id, sum(s.quantity) as total_quantity 62 | from sales s 63 | join product p 64 | on p.product_id = s.product_id 65 | group by 1 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /medium/Game Play Analysis 4.sql: -------------------------------------------------------------------------------- 1 | -- Question 91 2 | -- Table: Activity 3 | 4 | -- +--------------+---------+ 5 | -- | Column Name | Type | 6 | -- +--------------+---------+ 7 | -- | player_id | int | 8 | -- | device_id | int | 9 | -- | event_date | date | 10 | -- | games_played | int | 11 | -- +--------------+---------+ 12 | -- (player_id, event_date) is the primary key of this table. 13 | -- This table shows the activity of players of some game. 14 | -- Each row is a record of a player who logged in and played a number of games (possibly 0) 15 | -- before logging out on some day using some device. 16 | 17 | 18 | -- Write an SQL query that reports the fraction of players that logged in again 19 | -- on the day after the day they first logged in, rounded to 2 decimal places. 20 | -- In other words, you need to count the number of players that logged in for at least two consecutive 21 | -- days starting from their first login date, then divide that number by the total number of players. 22 | 23 | -- The query result format is in the following example: 24 | 25 | -- Activity table: 26 | -- +-----------+-----------+------------+--------------+ 27 | -- | player_id | device_id | event_date | games_played | 28 | -- +-----------+-----------+------------+--------------+ 29 | -- | 1 | 2 | 2016-03-01 | 5 | 30 | -- | 1 | 2 | 2016-03-02 | 6 | 31 | -- | 2 | 3 | 2017-06-25 | 1 | 32 | -- | 3 | 1 | 2016-03-02 | 0 | 33 | -- | 3 | 4 | 2018-07-03 | 5 | 34 | -- +-----------+-----------+------------+--------------+ 35 | 36 | -- Result table: 37 | -- +-----------+ 38 | -- | fraction | 39 | -- +-----------+ 40 | -- | 0.33 | 41 | -- +-----------+ 42 | -- Only the player with id 1 logged back in after the first day he had logged in so the answer is 1/3 = 0.33 43 | 44 | 45 | -- Solution 46 | select round(sum(a.cnt_consecutive)/count(distinct player_id),2) as fraction 47 | (select player_id, 48 | case when event_date -min(event_date) over( partition by player_id) =1 then 1 49 | else 0 end as cnt_consecutive 50 | from activity) a 51 | 52 | 53 | -------------------------------------------------------------------------------- /easy/Group sold products by the date.sql: -------------------------------------------------------------------------------- 1 | -- Question 116 2 | -- Table Activities: 3 | 4 | -- +-------------+---------+ 5 | -- | Column Name | Type | 6 | -- +-------------+---------+ 7 | -- | sell_date | date | 8 | -- | product | varchar | 9 | -- +-------------+---------+ 10 | -- There is no primary key for this table, it may contains duplicates. 11 | -- Each row of this table contains the product name and the date it was sold in a market. 12 | 13 | 14 | -- Write an SQL query to find for each date, the number of distinct products sold and their names. 15 | 16 | -- The sold-products names for each date should be sorted lexicographically. 17 | 18 | -- Return the result table ordered by sell_date. 19 | 20 | -- The query result format is in the following example. 21 | 22 | -- Activities table: 23 | -- +------------+-------------+ 24 | -- | sell_date | product | 25 | -- +------------+-------------+ 26 | -- | 2020-05-30 | Headphone | 27 | -- | 2020-06-01 | Pencil | 28 | -- | 2020-06-02 | Mask | 29 | -- | 2020-05-30 | Basketball | 30 | -- | 2020-06-01 | Bible | 31 | -- | 2020-06-02 | Mask | 32 | -- | 2020-05-30 | T-Shirt | 33 | -- +------------+-------------+ 34 | 35 | -- Result table: 36 | -- +------------+----------+------------------------------+ 37 | -- | sell_date | num_sold | products | 38 | -- +------------+----------+------------------------------+ 39 | -- | 2020-05-30 | 3 | Basketball,Headphone,T-shirt | 40 | -- | 2020-06-01 | 2 | Bible,Pencil | 41 | -- | 2020-06-02 | 1 | Mask | 42 | -- +------------+----------+------------------------------+ 43 | -- For 2020-05-30, Sold items were (Headphone, Basketball, T-shirt), we sort them lexicographically and separate them by comma. 44 | -- For 2020-06-01, Sold items were (Pencil, Bible), we sort them lexicographically and separate them by comma. 45 | -- For 2020-06-02, Sold item is (Mask), we just return it. 46 | 47 | -- Solution 48 | select sell_date,count(distinct product) as num_sold,array_agg(distinct product order by product) as products 49 | from activities 50 | group by sell_date 51 | order by sell_date 52 | -------------------------------------------------------------------------------- /easy/Find Users with invalid Emails.sql: -------------------------------------------------------------------------------- 1 | -- Table Users 2 | -- +---------------+---------+ 3 | -- | Column Name | Type | 4 | -- +---------------+---------+ 5 | -- | user_id | int | 6 | -- | name | varchar | 7 | -- | mail | varchar | 8 | -- +---------------+---------+ 9 | -- user_id is the primary key for this table. 10 | -- This table contains information of the users signed up in a website. Some e-mails are invalid. 11 | -- Write an SQL query to find the users who have valid emails 12 | 13 | -- A valid e-mail has a prefix name and a domain where: 14 | 15 | -- The prefix name is a string that may contain letters (upper or lower case), digits, underscore '_', period '.' and/or dash '-'. The prefix name must start with a letter. 16 | -- The domain is '@leetcode.com'. 17 | -- Return the result table in any order.bb 18 | 19 | -- Users 20 | +---------+-----------+-------------------------+ 21 | | user_id | name | mail | 22 | +---------+-----------+-------------------------+ 23 | | 1 | Winston | winston@leetcode.com | 24 | | 2 | Jonathan | jonathanisgreat | 25 | | 3 | Annabelle | bella-@leetcode.com | 26 | | 4 | Sally | sally.come@leetcode.com | 27 | | 5 | Marwan | quarz#2020@leetcode.com | 28 | | 6 | David | david69@gmail.com | 29 | | 7 | Shapiro | .shapo@leetcode.com | 30 | +---------+-----------+-------------------------+ 31 | 32 | -- Result table: 33 | +---------+-----------+-------------------------+ 34 | | user_id | name | mail | 35 | +---------+-----------+-------------------------+ 36 | | 1 | Winston | winston@leetcode.com | 37 | | 3 | Annabelle | bella-@leetcode.com | 38 | | 4 | Sally | sally.come@leetcode.com | 39 | +---------+-----------+-------------------------+ 40 | -- The mail of user 2 doesn't have a domain. 41 | -- The mail of user 5 has # sign which is not allowed. 42 | -- The mail of user 6 doesn't have leetcode domain. 43 | -- The mail of user 7 starts with a period. 44 | 45 | 46 | select * from users where mail not in (select mail from user where mail ~ "^[A-Za-z0-9_./-]*@leetcode.com") 47 | 48 | -------------------------------------------------------------------------------- /hard/Department top three salaries.sql: -------------------------------------------------------------------------------- 1 | -- Question 14 2 | -- The Employee table holds all employees. Every employee has an Id, and there is also a column for the department Id. 3 | 4 | -- +----+-------+--------+--------------+ 5 | -- | Id | Name | Salary | DepartmentId | 6 | -- +----+-------+--------+--------------+ 7 | -- | 1 | Joe | 85000 | 1 | 8 | -- | 2 | Henry | 80000 | 2 | 9 | -- | 3 | Sam | 60000 | 2 | 10 | -- | 4 | Max | 90000 | 1 | 11 | -- | 5 | Janet | 69000 | 1 | 12 | -- | 6 | Randy | 85000 | 1 | 13 | -- | 7 | Will | 70000 | 1 | 14 | -- +----+-------+--------+--------------+ 15 | -- The Department table holds all departments of the company. 16 | 17 | -- +----+----------+ 18 | -- | Id | Name | 19 | -- +----+----------+ 20 | -- | 1 | IT | 21 | -- | 2 | Sales | 22 | -- +----+----------+ 23 | -- Write a SQL query to find employees who earn the top three salaries in each of the department. For the above tables, your SQL query should return the following rows (order of rows does not matter). 24 | 25 | -- +------------+----------+--------+ 26 | -- | Department | Employee | Salary | 27 | -- +------------+----------+--------+ 28 | -- | IT | Max | 90000 | 29 | -- | IT | Randy | 85000 | 30 | -- | IT | Joe | 85000 | 31 | -- | IT | Will | 70000 | 32 | -- | Sales | Henry | 80000 | 33 | -- | Sales | Sam | 60000 | 34 | -- +------------+----------+--------+ 35 | -- Explanation: 36 | 37 | -- In IT department, Max earns the highest salary, both Randy and Joe earn the second highest salary, 38 | -- and Will earns the third highest salary. 39 | -- There are only two employees in the Sales department, 40 | -- Henry earns the highest salary while Sam earns the second highest salary. 41 | 42 | -- Solution 43 | 44 | with top_three_salaries as 45 | (Select d.Name as Department,e.Name as Employee, e.Salary as Salary, 46 | dense_rank() over (partition by d.Name order by e.Salary desc) as rk 47 | From Employee e 48 | inner join Department d 49 | on d.Id = e.DepartmentId) 50 | 51 | Select Department,Employee,Salary from top_three_salaries 52 | where rk <= 3 -------------------------------------------------------------------------------- /easy/Replace employee id with unique identifier.sql: -------------------------------------------------------------------------------- 1 | -- Question 48 2 | -- Table: Employees 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | id | int | 8 | -- | name | varchar | 9 | -- +---------------+---------+ 10 | -- id is the primary key for this table. 11 | -- Each row of this table contains the id and the name of an employee in a company. 12 | 13 | 14 | -- Table: EmployeeUNI 15 | 16 | -- +---------------+---------+ 17 | -- | Column Name | Type | 18 | -- +---------------+---------+ 19 | -- | id | int | 20 | -- | unique_id | int | 21 | -- +---------------+---------+ 22 | -- (id, unique_id) is the primary key for this table. 23 | -- Each row of this table contains the id and the corresponding unique id of an employee in the company. 24 | 25 | 26 | -- Write an SQL query to show the unique ID of each user, If a user doesn't have a unique ID replace just show null. 27 | 28 | -- Return the result table in any order. 29 | 30 | -- The query result format is in the following example: 31 | 32 | -- Employees table: 33 | -- +----+----------+ 34 | -- | id | name | 35 | -- +----+----------+ 36 | -- | 1 | Alice | 37 | -- | 7 | Bob | 38 | -- | 11 | Meir | 39 | -- | 90 | Winston | 40 | -- | 3 | Jonathan | 41 | -- +----+----------+ 42 | 43 | -- EmployeeUNI table: 44 | -- +----+-----------+ 45 | -- | id | unique_id | 46 | -- +----+-----------+ 47 | -- | 3 | 1 | 48 | -- | 11 | 2 | 49 | -- | 90 | 3 | 50 | -- +----+-----------+ 51 | 52 | -- EmployeeUNI table: 53 | -- +-----------+----------+ 54 | -- | unique_id | name | 55 | -- +-----------+----------+ 56 | -- | null | Alice | 57 | -- | null | Bob | 58 | -- | 2 | Meir | 59 | -- | 3 | Winston | 60 | -- | 1 | Jonathan | 61 | -- +-----------+----------+ 62 | 63 | -- Alice and Bob don't have a unique ID, We will show null instead. 64 | -- The unique ID of Meir is 2. 65 | -- The unique ID of Winston is 3. 66 | -- The unique ID of Jonathan is 1. 67 | 68 | -- Solution 69 | select eu.unique_id,e.name 70 | employees e 71 | left join EmployeeUNI eu 72 | on eu.id=e.id 73 | order by e.id 74 | 75 | -------------------------------------------------------------------------------- /easy/Find Total Time Spent by Each Employee.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Table Employees 3 | +-------------+------+ 4 | | Column Name | Type | 5 | +-------------+------+ 6 | | emp_id | int | 7 | | event_day | date | 8 | | in_time | int | 9 | | out_time | int | 10 | +-------------+------+ 11 | 12 | -- (emp_id, event_day, in_time) is the primary key of this table. 13 | -- The table shows the employees' entries and exits in an office. 14 | -- event_day is the day at which this event happened and in_time is the minute at which the employee entered the office and out_time is the time at which he got outnumbered from 1 to 1440. 15 | -- It's guaranteed that no two events on the same day intersect in time. 16 | 17 | -- Write an SQL query to calculate the total time in minutes spent by each employee on each day at the office. Note that within one day, an employee can enter and leave more than once. 18 | -- Return the result table in any order. 19 | -- The query result format is in the following example: 20 | 21 | -- Employees table: 22 | +--------+------------+---------+----------+ 23 | | emp_id | event_day | in_time | out_time | 24 | +--------+------------+---------+----------+ 25 | | 1 | 2020-11-28 | 4 | 32 | 26 | | 1 | 2020-11-28 | 55 | 200 | 27 | | 1 | 2020-12-03 | 1 | 42 | 28 | | 2 | 2020-11-28 | 3 | 33 | 29 | | 2 | 2020-12-09 | 47 | 74 | 30 | +--------+------------+---------+----------+ 31 | -- Result table: 32 | +------------+--------+------------+ 33 | | day | emp_id | total_time | 34 | +------------+--------+------------+ 35 | | 2020-11-28 | 1 | 173 | 36 | | 2020-11-28 | 2 | 30 | 37 | | 2020-12-03 | 1 | 41 | 38 | | 2020-12-09 | 2 | 27 | 39 | +------------+--------+------------+ 40 | -- Employee 1 has three events two on day 2020-11-28 with a total of (32 - 4) + (200-55) = 173 and one on day 2020-12-03 with a total of (42 - 1) = 41. 41 | -- Employee 2 has two events one on day 2020-11-28 with a total of (33-3) = 30 and one on day 2020-12-09 with a total of (74 - 47) = 27. 42 | 43 | 44 | -- Solution 45 | select event_day as day, emp_id, sum(out_time-in_time) as total_time 46 | from employees 47 | group by 1,2 48 | -------------------------------------------------------------------------------- /hard/Cumulative Salary.sql: -------------------------------------------------------------------------------- 1 | -- Question 102 2 | -- The Employee table holds the salary information in a year. 3 | 4 | -- Write a SQL to get the cumulative sum of an employee's salary over a period of 3 months but exclude the most recent month. 5 | 6 | -- The result should be displayed by 'Id' ascending, and then by 'Month' descending. 7 | 8 | -- Example 9 | -- Input 10 | 11 | -- | Id | Month | Salary | 12 | -- |----|-------|--------| 13 | -- | 1 | 1 | 20 | 14 | -- | 2 | 1 | 20 | 15 | -- | 1 | 2 | 30 | 16 | -- | 2 | 2 | 30 | 17 | -- | 3 | 2 | 40 | 18 | -- | 1 | 3 | 40 | 19 | -- | 3 | 3 | 60 | 20 | -- | 1 | 4 | 60 | 21 | -- | 3 | 4 | 70 | 22 | 23 | -- Output 24 | 25 | -- | Id | Month | Salary | 26 | -- |----|-------|--------| 27 | -- | 1 | 3 | 90 | 28 | -- | 1 | 2 | 50 | 29 | -- | 1 | 1 | 20 | 30 | -- | 2 | 1 | 20 | 31 | -- | 3 | 3 | 100 | 32 | -- | 3 | 2 | 40 | 33 | 34 | 35 | -- Explanation 36 | -- Employee '1' has 3 salary records for the following 3 months except the most recent month '4': salary 40 for month '3', 30 for month '2' and 20 for month '1' 37 | -- So the cumulative sum of salary of this employee over 3 months is 90(40+30+20), 50(30+20) and 20 respectively. 38 | 39 | -- | Id | Month | Salary | 40 | -- |----|-------|--------| 41 | -- | 1 | 3 | 90 | 42 | -- | 1 | 2 | 50 | 43 | -- | 1 | 1 | 20 | 44 | -- Employee '2' only has one salary record (month '1') except its most recent month '2'. 45 | -- | Id | Month | Salary | 46 | -- |----|-------|--------| 47 | -- | 2 | 1 | 20 | 48 | 49 | 50 | -- Employ '3' has two salary records except its most recent pay month '4': month '3' with 60 and month '2' with 40. So the cumulative salary is as following. 51 | -- | Id | Month | Salary | 52 | -- |----|-------|--------| 53 | -- | 3 | 3 | 100 | 54 | -- | 3 | 2 | 40 | 55 | 56 | -- Solution 57 | with t1 as( 58 | select *, max(month) over(partition by id) as recent_month 59 | from employee) 60 | 61 | select id, month, sum(salary) over(partition by id order by month rows between 2 preceding and current row) as salary 62 | from t1 63 | where month 1 and rk=2) or (num=1 and rk=1) 48 | -------------------------------------------------------------------------------- /easy/Immediate food delivery.sql: -------------------------------------------------------------------------------- 1 | -- Question 38 2 | -- Table: Delivery 3 | 4 | -- +-----------------------------+---------+ 5 | -- | Column Name | Type | 6 | -- +-----------------------------+---------+ 7 | -- | delivery_id | int | 8 | -- | customer_id | int | 9 | -- | order_date | date | 10 | -- | customer_pref_delivery_date | date | 11 | -- +-----------------------------+---------+ 12 | -- delivery_id is the primary key of this table. 13 | -- The table holds information about food delivery to customers that make orders at some date and specify a preferred delivery date (on the same order date or after it). 14 | 15 | 16 | -- If the preferred delivery date of the customer is the same as the order date then the order is called immediate otherwise it's called scheduled. 17 | 18 | -- Write an SQL query to find the percentage of immediate orders in the table, rounded to 2 decimal places. 19 | 20 | -- The query result format is in the following example: 21 | 22 | -- Delivery table: 23 | -- +-------------+-------------+------------+-----------------------------+ 24 | -- | delivery_id | customer_id | order_date | customer_pref_delivery_date | 25 | -- +-------------+-------------+------------+-----------------------------+ 26 | -- | 1 | 1 | 2019-08-01 | 2019-08-02 | 27 | -- | 2 | 5 | 2019-08-02 | 2019-08-02 | 28 | -- | 3 | 1 | 2019-08-11 | 2019-08-11 | 29 | -- | 4 | 3 | 2019-08-24 | 2019-08-26 | 30 | -- | 5 | 4 | 2019-08-21 | 2019-08-22 | 31 | -- | 6 | 2 | 2019-08-11 | 2019-08-13 | 32 | -- +-------------+-------------+------------+-----------------------------+ 33 | 34 | -- Result table: 35 | -- +----------------------+ 36 | -- | immediate_percentage | 37 | -- +----------------------+ 38 | -- | 33.33 | 39 | -- +----------------------+ 40 | -- The orders with delivery id 2 and 3 are immediate while the others are scheduled. 41 | 42 | 43 | -- Solution 44 | select round(avg(case when order_date= customer_pref_delivery_date then 1 else 0 end)*100,2) as immediate_percentage 45 | from delivery 46 | -------------------------------------------------------------------------------- /easy/Fix product Name Format.sql: -------------------------------------------------------------------------------- 1 | Table Sales 2 | 3 | +--------------+---------+ 4 | | Column Name | Type | 5 | +--------------+---------+ 6 | | sale_id | int | 7 | | product_name | varchar | 8 | | sale_date | date | 9 | +--------------+---------+ 10 | 11 | -- sale_id is the primary key for this table. 12 | -- Each row of this table contains the product name and the date it was sold. 13 | -- Since table Sales was filled manually in the year 2000, product_name may contain leading and/or trailing white spaces, also they are case-insensitive. 14 | 15 | -- Write an SQL query to report 16 | 17 | -- product_name in lowercase without leading or trailing white spaces. 18 | -- sale_date in the format (‘YYYY-MM’) 19 | -- total the number of times the product was sold in this month. 20 | -- Return the result table ordered by product_name in ascending order, in case of a tie order it by sale_date in ascending order. 21 | 22 | -- Sales 23 | +------------+------------------+--------------+ 24 | | sale_id | product_name | sale_date | 25 | +------------+------------------+--------------+ 26 | | 1 | LCPHONE | 2000-01-16 | 27 | | 2 | LCPhone | 2000-01-17 | 28 | | 3 | LcPhOnE | 2000-02-18 | 29 | | 4 | LCKeyCHAiN | 2000-02-19 | 30 | | 5 | LCKeyChain | 2000-02-28 | 31 | | 6 | Matryoshka | 2000-03-31 | 32 | +------------+------------------+--------------+ 33 | 34 | -- Result table: 35 | +--------------+--------------+----------+ 36 | | product_name | sale_date | total | 37 | +--------------+--------------+----------+ 38 | | lcphone | 2000-01 | 2 | 39 | | lckeychain | 2000-02 | 2 | 40 | | lcphone | 2000-02 | 1 | 41 | | matryoshka | 2000-03 | 1 | 42 | +--------------+--------------+----------+ 43 | 44 | -- In January, 2 LcPhones were sold, please note that the product names are not case sensitive and may contain spaces. 45 | -- In Februery, 2 LCKeychains and 1 LCPhone were sold. 46 | -- In March, 1 matryoshka was sold. 47 | 48 | select trim(lower(product_name)) as product_name, 49 | to_char(sale_date,"YYYY-MM")::date as sale_date, 50 | count(sale_id) as total 51 | from Sales 52 | group by 1,2 53 | order by 1, 2 54 | 55 | -------------------------------------------------------------------------------- /medium/Apples _ Oranges.sql: -------------------------------------------------------------------------------- 1 | -- Question 66 2 | -- Table: Sales 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | sale_date | date | 8 | -- | fruit | enum | 9 | -- | sold_num | int | 10 | -- +---------------+---------+ 11 | -- (sale_date,fruit) is the primary key for this table. 12 | -- This table contains the sales of "apples" and "oranges" sold each day. 13 | 14 | 15 | -- Write an SQL query to report the difference between number of apples and oranges sold each day. 16 | 17 | -- Return the result table ordered by sale_date in format ('YYYY-MM-DD'). 18 | 19 | -- The query result format is in the following example: 20 | 21 | -- Sales table: 22 | -- +------------+------------+-------------+ 23 | -- | sale_date | fruit | sold_num | 24 | -- +------------+------------+-------------+ 25 | -- | 2020-05-01 | apples | 10 | 26 | -- | 2020-05-01 | oranges | 8 | 27 | -- | 2020-05-02 | apples | 15 | 28 | -- | 2020-05-02 | oranges | 15 | 29 | -- | 2020-05-03 | apples | 20 | 30 | -- | 2020-05-03 | oranges | 0 | 31 | -- | 2020-05-04 | apples | 15 | 32 | -- | 2020-05-04 | oranges | 16 | 33 | -- +------------+------------+-------------+ 34 | 35 | -- Result table: 36 | -- +------------+--------------+ 37 | -- | sale_date | diff | 38 | -- +------------+--------------+ 39 | -- | 2020-05-01 | 2 | 40 | -- | 2020-05-02 | 0 | 41 | -- | 2020-05-03 | 20 | 42 | -- | 2020-05-04 | -1 | 43 | -- +------------+--------------+ 44 | 45 | -- Day 2020-05-01, 10 apples and 8 oranges were sold (Difference 10 - 8 = 2). 46 | -- Day 2020-05-02, 15 apples and 15 oranges were sold (Difference 15 - 15 = 0). 47 | -- Day 2020-05-03, 20 apples and 0 oranges were sold (Difference 20 - 0 = 20). 48 | -- Day 2020-05-04, 15 apples and 16 oranges were sold (Difference 15 - 16 = -1). 49 | 50 | 51 | -- Solution 52 | select sale_date, a.sold_num -sold as diff 53 | ((select * from sales 54 | where fruit="apples") a 55 | join 56 | (select sale_date,fruit,sold_num as sold 57 | from sales 58 | where fruit="oranges") b 59 | on b.sale_date = a.sale_date) 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /easy/Friendly Movies streamed list.sql: -------------------------------------------------------------------------------- 1 | -- Question 115 2 | -- Write an SQL query to report the distinct titles of the kid-friendly movies streamed in June 2020. 3 | 4 | -- Return the result table in any order. 5 | 6 | -- The query result format is in the following example. 7 | 8 | 9 | 10 | -- TVProgram table: 11 | -- +--------------------+--------------+-------------+ 12 | -- | program_date | content_id | channel | 13 | -- +--------------------+--------------+-------------+ 14 | -- | 2020-06-10 08:00 | 1 | LC-Channel | 15 | -- | 2020-05-11 12:00 | 2 | LC-Channel | 16 | -- | 2020-05-12 12:00 | 3 | LC-Channel | 17 | -- | 2020-05-13 14:00 | 4 | Disney Ch | 18 | -- | 2020-06-18 14:00 | 4 | Disney Ch | 19 | -- | 2020-07-15 16:00 | 5 | Disney Ch | 20 | -- +--------------------+--------------+-------------+ 21 | 22 | -- Content table: 23 | -- +------------+----------------+---------------+---------------+ 24 | -- | content_id | title | Kids_content | content_type | 25 | -- +------------+----------------+---------------+---------------+ 26 | -- | 1 | Leetcode Movie | N | Movies | 27 | -- | 2 | Alg. for Kids | Y | Series | 28 | -- | 3 | Database Sols | N | Series | 29 | -- | 4 | Aladdin | Y | Movies | 30 | -- | 5 | Cinderella | Y | Movies | 31 | -- +------------+----------------+---------------+---------------+ 32 | 33 | -- Result table: 34 | -- +--------------+ 35 | -- | title | 36 | -- +--------------+ 37 | -- | Aladdin | 38 | -- +--------------+ 39 | -- "Leetcode Movie" is not a content for kids. 40 | -- "Alg. for Kids" is not a movie. 41 | -- "Database Sols" is not a movie 42 | -- "Alladin" is a movie, content for kids and was streamed in June 2020. 43 | -- "Cinderella" was not streamed in June 2020. 44 | 45 | 46 | -- Solution 47 | select distinct c.title as title 48 | from TVProgram tvp 49 | inner join content c 50 | on c.content_id = tvp.content_id 51 | where c.Kids_content ="Y" andc.content_type ="Movies" 52 | and (extract(month from tvp.program_date) =6 and extract(year from tvp.program_date) =2020) 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /medium/Active Businesses.sql: -------------------------------------------------------------------------------- 1 | -- Question 65 2 | -- Table: Events 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | business_id | int | 8 | -- | event_type | varchar | 9 | -- | occurences | int | 10 | -- +---------------+---------+ 11 | -- (business_id, event_type) is the primary key of this table. 12 | -- Each row in the table logs the info that an event of some type occured at some business for a number of times. 13 | 14 | 15 | -- Write an SQL query to find all active businesses. 16 | 17 | -- An active business is a business that has more than one event type with occurences greater than the average occurences of that event type among all businesses. 18 | 19 | -- The query result format is in the following example: 20 | 21 | -- Events table: 22 | -- +-------------+------------+------------+ 23 | -- | business_id | event_type | occurences | average 24 | -- +-------------+------------+------------+ 25 | -- | 1 | reviews | 7 | 5 1 26 | -- | 3 | reviews | 3 | 5 27 | -- | 1 | ads | 11 | 8 28 | -- | 2 | ads | 7 | 8 29 | -- | 3 | ads | 6 | 8 30 | -- | 1 | page views | 3 | 7.5 31 | -- | 2 | page views | 12 | 7.5 32 | -- +-------------+------------+------------+ 33 | 34 | -- Result table: 35 | -- +-------------+ 36 | -- | business_id | 37 | -- +-------------+ 38 | -- | 1 | 39 | -- | 8 | 40 | -- +-------------+ 41 | -- Average for 'reviews', 'ads' and 'page views' are (7+3)/2=5, (11+7+6)/3=8, (3+12)/2=7.5 respectively. 42 | -- Business with id 1 has 7 'reviews' events (more than 5) and 11 'ads' events (more than 8) so it is an active business. 43 | 44 | 45 | -- Solution 1 46 | select distinct a.business_id 47 | from 48 | (select business_id,occurences,avg(occurences) over(partition by event_type) as average 49 | from events) a 50 | where a.occurences > a.average 51 | 52 | -- Solution 2 53 | select c.business_id 54 | from( 55 | select * 56 | from events e 57 | join 58 | (select event_type as event, round(avg(occurences),2) as average from events group by event_type) b 59 | on e.event_type = b.event) c 60 | where c.occurences>c.average 61 | group by c.business_id 62 | having count(*) > 1 63 | -------------------------------------------------------------------------------- /medium/Get the second most recent activity.sql: -------------------------------------------------------------------------------- 1 | -- Question 109 2 | -- Table: UserActivity 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | username | varchar | 8 | -- | activity | varchar | 9 | -- | startDate | Date | 10 | -- | endDate | Date | 11 | -- +---------------+---------+ 12 | -- This table does not contain primary key. 13 | -- This table contain information about the activity performed of each user in a period of time. 14 | -- A person with username performed a activity from startDate to endDate. 15 | 16 | -- Write an SQL query to show the second most recent activity of each user. 17 | 18 | -- If the user only has one activity, return that one. 19 | 20 | -- A user can't perform more than one activity at the same time. Return the result table in any order. 21 | 22 | -- The query result format is in the following example: 23 | 24 | -- UserActivity table: 25 | -- +------------+--------------+-------------+-------------+ 26 | -- | username | activity | startDate | endDate | 27 | -- +------------+--------------+-------------+-------------+ 28 | -- | Alice | Travel | 2020-02-12 | 2020-02-20 | 29 | -- | Alice | Dancing | 2020-02-21 | 2020-02-23 | 30 | -- | Alice | Travel | 2020-02-24 | 2020-02-28 | 31 | -- | Bob | Travel | 2020-02-11 | 2020-02-18 | 32 | -- +------------+--------------+-------------+-------------+ 33 | 34 | -- Result table: 35 | -- +------------+--------------+-------------+-------------+ 36 | -- | username | activity | startDate | endDate | 37 | -- +------------+--------------+-------------+-------------+ 38 | -- | Alice | Dancing | 2020-02-21 | 2020-02-23 | 39 | -- | Bob | Travel | 2020-02-11 | 2020-02-18 | 40 | -- +------------+--------------+-------------+-------------+ 41 | 42 | -- The most recent activity of Alice is Travel from 2020-02-24 to 2020-02-28, before that she was dancing from 2020-02-21 to 2020-02-23. 43 | -- Bob only has one record, we just take that one. 44 | 45 | -- Solution 46 | select username, activity, startdate, enddate 47 | from 48 | (select *, 49 | rank() over(partition by username order by startdate desc) as rk, 50 | count(username) over(partition by username) as cnt 51 | from useractivity) a 52 | where a.rk = 2 or cnt = 1 53 | -------------------------------------------------------------------------------- /medium/Strong Friendship.sql: -------------------------------------------------------------------------------- 1 | -- Table: Friendship 2 | +-------------+------+ 3 | | Column Name | Type | 4 | +-------------+------+ 5 | | user1_id | int | 6 | | user2_id | int | 7 | +-------------+------+ 8 | --(user1_id, user2_id) is the primary key for this table. 9 | --Each row of this table indicates that the users user1_id and user2_id are friends. 10 | --Note that user1_id < user2_id. 11 | 12 | --A friendship between a pair of friends x and y is strong if x and y have at least three common friends. 13 | --Write an SQL query to find all the strong friendships. 14 | --Note that the result table should not contain duplicates with user1_id < user2_id. 15 | --Return the result table in any order. 16 | --The query result format is in the following example: 17 | 18 | --Friendship table: 19 | +----------+----------+ 20 | | user1_id | user2_id | 21 | +----------+----------+ 22 | | 1 | 2 | 23 | | 1 | 3 | 24 | | 2 | 3 | 25 | | 1 | 4 | 26 | | 2 | 4 | 27 | | 1 | 5 | 28 | | 2 | 5 | 29 | | 1 | 7 | 30 | | 3 | 7 | 31 | | 1 | 6 | 32 | | 3 | 6 | 33 | | 2 | 6 | 34 | +----------+----------+ 35 | 36 | --Result table: 37 | +----------+----------+---------------+ 38 | | user1_id | user2_id | common_friend | 39 | +----------+----------+---------------+ 40 | | 1 | 2 | 4 | 41 | | 1 | 3 | 3 | 42 | +----------+----------+---------------+ 43 | --Users 1 and 2 have 4 common friends (3, 4, 5, and 6). 44 | --Users 1 and 3 have 3 common friends (2, 6, and 7). 45 | --We did not include the friendship of users 2 and 3 because they only have two common friends (1 and 6). 46 | 47 | -- Solution 48 | with friendtable as( 49 | select user1_id as userid, user2_id as friend 50 | from friendship 51 | union 52 | select user2_id as userid, user1_id as friend 53 | from friendship 54 | ) 55 | 56 | select f1.userid as user1_id, f2.userid as user2_id, count(f1.friend) as common_friend 57 | from friendtable as f1 58 | join friendtable as f2 59 | on f1.friend=f2.friend 60 | where f1.userid=3 67 | -------------------------------------------------------------------------------- /medium/ Count Salary Categories.sql: -------------------------------------------------------------------------------- 1 | -- Table: Accounts 2 | 3 | +-------------+------+ 4 | | Column Name | Type | 5 | +-------------+------+ 6 | | account_id | int | 7 | | income | int | 8 | +-------------+------+ 9 | --account_id is the primary key for this table. 10 | --Each row contains information about the monthly income for one bank account. 11 | 12 | --Write an SQL query to report the number of bank accounts of each salary category. The salary categories are: 13 | 14 | --“Low Salary”: All the salaries strictly less than $20000. 15 | --“Average Salary”: All the salaries in the inclusive range [$20000, $50000]. 16 | --“High Salary”: All the salaries strictly greater than $50000. 17 | --The result table must contain all three categories. If there are no accounts in a category, then report 0. Return the result table in any order. 18 | --The query result format is in the following example. 19 | 20 | --Accounts table: 21 | +------------+--------+ 22 | | account_id | income | 23 | +------------+--------+ 24 | | 3 | 108939 | 25 | | 2 | 12747 | 26 | | 8 | 87709 | 27 | | 6 | 91796 | 28 | +------------+--------+ 29 | 30 | --Result table: 31 | +----------------+----------------+ 32 | | category | accounts_count | 33 | +----------------+----------------+ 34 | | Low Salary | 1 | 35 | | Average Salary | 0 | 36 | | High Salary | 3 | 37 | +----------------+----------------+ 38 | 39 | --Low Salary: Account 2. 40 | --Average Salary: No accounts. 41 | --High Salary: Accounts 3, 6, and 8. 42 | 43 | -- Solution 1 44 | select a.category,coalesce(count(*),0) as accounts_count 45 | from 46 | (select account_id, 47 | case when income < 20000 then "Low Salary" 48 | when income >= 20000 and income <=50000 then "Average Salary" 49 | else "High Salary" end as category 50 | from Accounts) a 51 | left join Accounts b 52 | on b.account_id = b.account_id 53 | group by a.category 54 | order by accounts_count 55 | 56 | -- Solution 2 57 | select "Low Salary" as category, count(*) as accounts_count from Accounts where income < 20000 58 | union 59 | select "Average Salary" as category, count(*) as accounts_count from Accounts where 20000 <= income and income <= 50000 60 | union 61 | select "High Salary" as category, count(*) as accounts_count from Accounts where 50000 < income 62 | 63 | 64 | -------------------------------------------------------------------------------- /medium/Count student number in departments.sql: -------------------------------------------------------------------------------- 1 | -- Question 87 2 | -- A university uses 2 data tables, student and department, to store data about its students 3 | -- and the departments associated with each major. 4 | 5 | -- Write a query to print the respective department name and number of students majoring in each 6 | -- department for all departments in the department table (even ones with no current students). 7 | 8 | -- Sort your results by descending number of students; if two or more departments have the same number of students, 9 | -- then sort those departments alphabetically by department name. 10 | 11 | -- The student is described as follow: 12 | 13 | -- | Column Name | Type | 14 | -- |--------------|-----------| 15 | -- | student_id | Integer | 16 | -- | student_name | String | 17 | -- | gender | Character | 18 | -- | dept_id | Integer | 19 | -- where student_id is the student's ID number, student_name is the student's name, gender is their gender, and dept_id is the department ID associated with their declared major. 20 | 21 | -- And the department table is described as below: 22 | 23 | -- | Column Name | Type | 24 | -- |-------------|---------| 25 | -- | dept_id | Integer | 26 | -- | dept_name | String | 27 | -- where dept_id is the department's ID number and dept_name is the department name. 28 | 29 | -- Here is an example input: 30 | -- student table: 31 | 32 | -- | student_id | student_name | gender | dept_id | 33 | -- |------------|--------------|--------|---------| 34 | -- | 1 | Jack | M | 1 | 35 | -- | 2 | Jane | F | 1 | 36 | -- | 3 | Mark | M | 2 | 37 | -- department table: 38 | 39 | -- | dept_id | dept_name | 40 | -- |---------|-------------| 41 | -- | 1 | Engineering | 42 | -- | 2 | Science | 43 | -- | 3 | Law | 44 | -- The Output should be: 45 | 46 | -- | dept_name | student_number | 47 | -- |-------------|----------------| 48 | -- | Engineering | 2 | 49 | -- | Science | 1 | 50 | -- | Law | 0 | 51 | 52 | 53 | -- Solution 54 | select d.dept_name as dept_name, coalesce(count(s.dept_id),0) as student_number 55 | from department d 56 | left join student s 57 | on s.dept_id = d.dept_id 58 | group by d.dept_name 59 | order by student_number desc, dept_name 60 | -------------------------------------------------------------------------------- /easy/Friend Requests 1.sql: -------------------------------------------------------------------------------- 1 | -- Question 49 2 | -- In social network like Facebook or Twitter, people send friend requests and accept others’ requests as well. Now given two tables as below: 3 | 4 | 5 | -- Table: friend_request 6 | -- | sender_id | send_to_id |request_date| 7 | -- |-----------|------------|------------| 8 | -- | 1 | 2 | 2016_06-01 | 9 | -- | 1 | 3 | 2016_06-01 | 10 | -- | 1 | 4 | 2016_06-01 | 11 | -- | 2 | 3 | 2016_06-02 | 12 | -- | 3 | 4 | 2016-06-09 | 13 | 14 | 15 | -- Table: request_accepted 16 | -- | requester_id | accepter_id |accept_date | 17 | -- |--------------|-------------|------------| 18 | -- | 1 | 2 | 2016_06-03 | 19 | -- | 1 | 3 | 2016-06-08 | 20 | -- | 2 | 3 | 2016-06-08 | 21 | -- | 3 | 4 | 2016-06-09 | 22 | -- | 3 | 4 | 2016-06-10 | 23 | 24 | 25 | -- Write a query to find the overall acceptance rate of requests rounded to 2 decimals, which is the number of acceptance divide the number of requests. 26 | 27 | 28 | -- For the sample data above, your query should return the following result. 29 | 30 | 31 | -- |accept_rate| 32 | -- |-----------| 33 | -- | 0.80| 34 | 35 | 36 | -- Note: 37 | -- The accepted requests are not necessarily from the table friend_request. In this case, you just need to simply count the total accepted requests (no matter whether they are in the original requests), and divide it by the number of requests to get the acceptance rate. 38 | -- It is possible that a sender sends multiple requests to the same receiver, and a request could be accepted more than once. In this case, the ‘duplicated’ requests or acceptances are only counted once. 39 | -- If there is no requests at all, you should return 0.00 as the accept_rate. 40 | 41 | 42 | -- Explanation: There are 4 unique accepted requests, and there are 5 requests in total. 43 | -- So the rate is 0.80. 44 | 45 | -- Solution 46 | with t1 as 47 | ( 48 | select distinct sender_id, send_to_id 49 | from friend_request 50 | ), t2 as 51 | ( 52 | select distinct requester_id, accepter_id 53 | from request_accepted 54 | ) 55 | 56 | Select 57 | ifnull(( 58 | select distinct 59 | round((select count(*) from t2) / ( select count(*) from t1),2) from t1,t2 60 | ),0) 'accept_rate' 61 | -------------------------------------------------------------------------------- /easy/Project Employees 1.sql: -------------------------------------------------------------------------------- 1 | -- Question 26 2 | -- Table: Project 3 | 4 | -- +-------------+---------+ 5 | -- | Column Name | Type | 6 | -- +-------------+---------+ 7 | -- | project_id | int | 8 | -- | employee_id | int | 9 | -- +-------------+---------+ 10 | -- (project_id, employee_id) is the primary key of this table. 11 | -- employee_id is a foreign key to Employee table. 12 | -- Table: Employee 13 | 14 | -- +------------------+---------+ 15 | -- | Column Name | Type | 16 | -- +------------------+---------+ 17 | -- | employee_id | int | 18 | -- | name | varchar | 19 | -- | experience_years | int | 20 | -- +------------------+---------+ 21 | -- employee_id is the primary key of this table. 22 | 23 | 24 | -- Write an SQL query that reports the average experience years of all the employees for each project, rounded to 2 digits. 25 | 26 | -- The query result format is in the following example: 27 | 28 | -- Project table: 29 | -- +-------------+-------------+ 30 | -- | project_id | employee_id | 31 | -- +-------------+-------------+ 32 | -- | 1 | 1 | 33 | -- | 1 | 2 | 34 | -- | 1 | 3 | 35 | -- | 2 | 1 | 36 | -- | 2 | 4 | 37 | -- +-------------+-------------+ 38 | 39 | -- Employee table: 40 | -- +-------------+--------+------------------+ 41 | -- | employee_id | name | experience_years | 42 | -- +-------------+--------+------------------+ 43 | -- | 1 | Khaled | 3 | 44 | -- | 2 | Ali | 2 | 45 | -- | 3 | John | 1 | 46 | -- | 4 | Doe | 2 | 47 | -- +-------------+--------+------------------+ 48 | 49 | -- Result table: 50 | -- +-------------+---------------+ 51 | -- | project_id | average_years | 52 | -- +-------------+---------------+ 53 | -- | 1 | 2.00 | 54 | -- | 2 | 2.50 | 55 | -- +-------------+---------------+ 56 | -- The average experience years for the first project is (3 + 2 + 1) / 3 = 2.00 and for the second project is (3 + 2) / 2 = 2.50 57 | 58 | 59 | -- Solution 60 | Select p.project_id,round(avg(e.experience_years),2) as average_years 61 | from Project p 62 | inner join employee e 63 | on e.employee_id = p.employee_id 64 | group by 1 65 | order by 2 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /medium/Active Users.sql: -------------------------------------------------------------------------------- 1 | --Question 94 2 | -- Table Accounts: 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | id | int | 8 | -- | name | varchar | 9 | -- +---------------+---------+ 10 | -- the id is the primary key for this table. 11 | -- This table contains the account id and the user name of each account. 12 | 13 | -- Table Logins: 14 | 15 | -- +---------------+---------+ 16 | -- | Column Name | Type | 17 | -- +---------------+---------+ 18 | -- | id | int | 19 | -- | login_date | date | 20 | -- +---------------+---------+ 21 | -- There is no primary key for this table, it may contain duplicates. 22 | -- This table contains the account id of the user who logged in and the login date. A user may log in multiple times in the day. 23 | 24 | 25 | -- Write an SQL query to find the id and the name of active users. 26 | 27 | -- Active users are those who logged in to their accounts for 5 or more consecutive days. 28 | 29 | -- Return the result table ordered by the id. 30 | 31 | -- The query result format is in the following example: 32 | 33 | -- Accounts table: 34 | -- +----+----------+ 35 | -- | id | name | 36 | -- +----+----------+ 37 | -- | 1 | Winston | 38 | -- | 7 | Jonathan | 39 | -- +----+----------+ 40 | 41 | -- Logins table: 42 | -- +----+------------+ 43 | -- | id | login_date | 44 | -- +----+------------+ 45 | -- | 7 | 2020-05-30 | 46 | -- | 1 | 2020-05-30 | 47 | -- | 7 | 2020-05-31 | 48 | -- | 7 | 2020-06-01 | 49 | -- | 7 | 2020-06-02 | 50 | -- | 7 | 2020-06-02 | 51 | -- | 7 | 2020-06-03 | 52 | -- | 1 | 2020-06-07 | 53 | -- | 7 | 2020-06-10 | 54 | -- +----+------------+ 55 | 56 | -- Result table: 57 | -- +----+----------+ 58 | -- | id | name | 59 | -- +----+----------+ 60 | -- | 7 | Jonathan | 61 | -- +----+----------+ 62 | -- User Winston with id = 1 logged in 2 times only in 2 different days, so, Winston is not an active user. 63 | -- User Jonathan with id = 7 logged in 7 times in 6 different days, five of them were consecutive days, so, Jonathan is an active user. 64 | 65 | -- Solution 66 | select distinct l1.id,a.name 67 | from Logins l1 68 | join Logins l2 69 | on l2.id =l1.id 70 | and datediff(l1.login_date,l2.login_date) between 1 and 4 71 | join Accounts a on a.id= l1.id 72 | group by l1.id,l1.login_date 73 | having count(distinct l2.login_date) = 4 74 | -------------------------------------------------------------------------------- /easy/Create Session bar chart.sql: -------------------------------------------------------------------------------- 1 | -- Question 2 2 | -- Table: Sessions 3 | 4 | -- +---------------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------------+---------+ 7 | -- | session_id | int | 8 | -- | duration | int | 9 | -- +---------------------+---------+ 10 | -- session_id is the primary key for this table. 11 | -- duration is the time in seconds that a user has visited the application. 12 | 13 | 14 | -- You want to know how long a user visits your application. You decided to create bins of "[0-5>", "[5-10>", "[10-15>" and "15 minutes or more" and count the number of sessions on it. 15 | 16 | -- Write an SQL query to report the (bin, total) in any order. 17 | 18 | -- The query result format is in the following example. 19 | 20 | -- Sessions table: 21 | -- +-------------+---------------+ 22 | -- | session_id | duration | 23 | -- +-------------+---------------+ 24 | -- | 1 | 30 | 25 | -- | 2 | 199 | 26 | -- | 3 | 299 | 27 | -- | 4 | 580 | 28 | -- | 5 | 1000 | 29 | -- +-------------+---------------+ 30 | 31 | -- Result table: 32 | -- +--------------+--------------+ 33 | -- | bin | total | 34 | -- +--------------+--------------+ 35 | -- | [0-5> | 3 | 36 | -- | [5-10> | 1 | 37 | -- | [10-15> | 0 | 38 | -- | 15 or more | 1 | 39 | -- +--------------+--------------+ 40 | 41 | -- For session_id 1, 2 and 3 have a duration greater or equal than 0 minutes and less than 5 minutes. 42 | -- For session_id 4 has a duration greater or equal than 5 minutes and less than 10 minutes. 43 | -- There are no session with a duration greater or equial than 10 minutes and less than 15 minutes. 44 | -- For session_id 5 has a duration greater or equal than 15 minutes. 45 | 46 | -- Solution 47 | (select '[0-5>' as bin, 48 | sum(case when duration/60 < 5 then 1 else 0 end) as total from Sessions) 49 | union 50 | (select '[5-10>' as bin, 51 | sum(case when ((duration/60 >= 5) and (duration/60 < 10)) then 1 else 0 end) as total from Sessions) 52 | union 53 | (select '[10-15>' as bin, 54 | sum(case when ((duration/60 >= 10) and (duration/60 < 15)) then 1 else 0 end) as total from Sessions) 55 | union 56 | (select '15 or more' as bin, 57 | sum(case when duration/60 >= 15 then 1 else 0 end) as total from Sessions) -------------------------------------------------------------------------------- /medium/Game Play Analysis 3.sql: -------------------------------------------------------------------------------- 1 | -- Question 62 2 | -- Table: Activity 3 | -- +--------------+---------+ 4 | -- | Column Name | Type | 5 | -- +--------------+---------+ 6 | -- | player_id | int | 7 | -- | device_id | int | 8 | -- | event_date | date | 9 | -- | games_played | int | 10 | -- +--------------+---------+ 11 | -- (player_id, event_date) is the primary key of this table. 12 | -- This table shows the activity of players of some game. 13 | -- Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device. 14 | 15 | 16 | -- Write an SQL query that reports for each player and date, how many games played so far by the player. That is, the total number of games played by the player until that date. Check the example for clarity. 17 | 18 | -- The query result format is in the following example: 19 | 20 | -- Activity table: 21 | -- +-----------+-----------+------------+--------------+ 22 | -- | player_id | device_id | event_date | games_played | 23 | -- +-----------+-----------+------------+--------------+ 24 | -- | 1 | 2 | 2016-03-01 | 5 | 25 | -- | 1 | 2 | 2016-05-02 | 6 | 26 | -- | 1 | 3 | 2017-06-25 | 1 | 27 | -- | 3 | 1 | 2016-03-02 | 0 | 28 | -- | 3 | 4 | 2018-07-03 | 5 | 29 | -- +-----------+-----------+------------+--------------+ 30 | 31 | -- Result table: 32 | -- +-----------+------------+---------------------+ 33 | -- | player_id | event_date | games_played_so_far | 34 | -- +-----------+------------+---------------------+ 35 | -- | 1 | 2016-03-01 | 5 | 36 | -- | 1 | 2016-05-02 | 11 | 37 | -- | 1 | 2017-06-25 | 12 | 38 | -- | 3 | 2016-03-02 | 0 | 39 | -- | 3 | 2018-07-03 | 5 | 40 | -- +-----------+------------+---------------------+ 41 | -- For the player with id 1, 5 + 6 = 11 games played by 2016-05-02, and 5 + 6 + 1 = 12 games played by 2017-06-25. 42 | -- For the player with id 3, 0 + 5 = 5 games played by 2018-07-03. 43 | -- Note that for each player we only care about the days when the player logged in. 44 | 45 | -- Solution 46 | select player_id,event_date, 47 | sum(games_played) over(partition by player_id order by event_date) as games_played_so_far 48 | from activity 49 | order by 1,2 -------------------------------------------------------------------------------- /easy/User activity for past 30 days 1.sql: -------------------------------------------------------------------------------- 1 | -- Question 40 2 | -- Table: Activity 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | user_id | int | 8 | -- | session_id | int | 9 | -- | activity_date | date | 10 | -- | activity_type | enum | 11 | -- +---------------+---------+ 12 | -- There is no primary key for this table, it may have duplicate rows. 13 | -- The activity_type column is an ENUM of type ('open_session', 'end_session', 'scroll_down', 'send_message'). 14 | -- The table shows the user activities for a social media website. 15 | -- Note that each session belongs to exactly one user. 16 | 17 | 18 | -- Write an SQL query to find the daily active user count for a period of 30 days ending 2019-07-27 inclusively. A user was active on some day if he/she made at least one activity on that day. 19 | 20 | -- The query result format is in the following example: 21 | 22 | -- Activity table: 23 | -- +---------+------------+---------------+---------------+ 24 | -- | user_id | session_id | activity_date | activity_type | 25 | -- +---------+------------+---------------+---------------+ 26 | -- | 1 | 1 | 2019-07-20 | open_session | 27 | -- | 1 | 1 | 2019-07-20 | scroll_down | 28 | -- | 1 | 1 | 2019-07-20 | end_session | 29 | -- | 2 | 4 | 2019-07-20 | open_session | 30 | -- | 2 | 4 | 2019-07-21 | send_message | 31 | -- | 2 | 4 | 2019-07-21 | end_session | 32 | -- | 3 | 2 | 2019-07-21 | open_session | 33 | -- | 3 | 2 | 2019-07-21 | send_message | 34 | -- | 3 | 2 | 2019-07-21 | end_session | 35 | -- | 4 | 3 | 2019-06-25 | open_session | 36 | -- | 4 | 3 | 2019-06-25 | end_session | 37 | -- +---------+------------+---------------+---------------+ 38 | 39 | -- Result table: 40 | -- +------------+--------------+ 41 | -- | day | active_users | 42 | -- +------------+--------------+ 43 | -- | 2019-07-20 | 2 | 44 | -- | 2019-07-21 | 2 | 45 | -- +------------+--------------+ 46 | -- Note that we do not care about days with zero active users. 47 | 48 | 49 | -- Solution 50 | select activity_date as day, 51 | count(distinct user_id) as active_users 52 | from activity 53 | where activity_date > "2019-06-26" and activity_date < "2019-07-27" 54 | group by activity_date 55 | 56 | -------------------------------------------------------------------------------- /easy/Daily Leads and Partners.sql: -------------------------------------------------------------------------------- 1 | -- Table DailySales 2 | 3 | +-------------+---------+ 4 | | Column Name | Type | 5 | +-------------+---------+ 6 | | date_id | date | 7 | | make_name | varchar | 8 | | lead_id | int | 9 | | partner_id | int | 10 | +-------------+---------+ 11 | -- This table does not have a primary key. 12 | -- This table contains the date and the name of the product sold and the IDs of the lead and partner it was sold to. 13 | -- The name consists of only lowercase English letters. 14 | 15 | -- Write an SQL query that will, for each date_id and make_name, return the number of distinct lead_id’s and distinct partner_id’s. 16 | -- Return the result table in any order. 17 | -- The query result format is in the following example: 18 | 19 | -- DailySales table: 20 | +-----------+-----------+---------+------------+ 21 | | date_id | make_name | lead_id | partner_id | 22 | +-----------+-----------+---------+------------+ 23 | | 2020-12-8 | toyota | 0 | 1 | 24 | | 2020-12-8 | toyota | 1 | 0 | 25 | | 2020-12-8 | toyota | 1 | 2 | 26 | | 2020-12-7 | toyota | 0 | 2 | 27 | | 2020-12-7 | toyota | 0 | 1 | 28 | | 2020-12-8 | honda | 1 | 2 | 29 | | 2020-12-8 | honda | 2 | 1 | 30 | | 2020-12-7 | honda | 0 | 1 | 31 | | 2020-12-7 | honda | 1 | 2 | 32 | | 2020-12-7 | honda | 2 | 1 | 33 | +-----------+-----------+---------+------------+ 34 | -- Result table: 35 | +-----------+-----------+--------------+-----------------+ 36 | | date_id | make_name | unique_leads | unique_partners | 37 | +-----------+-----------+--------------+-----------------+ 38 | | 2020-12-8 | toyota | 2 | 3 | 39 | | 2020-12-7 | toyota | 1 | 2 | 40 | | 2020-12-8 | honda | 2 | 2 | 41 | | 2020-12-7 | honda | 3 | 2 | 42 | +-----------+-----------+--------------+-----------------+ 43 | -- For 2020-12-8, toyota gets leads = [0, 1] and partners = [0, 1, 2] while honda gets leads = [1, 2] and partners = [1, 2]. 44 | -- For 2020-12-7, toyota gets leads = [0] and partners = [1, 2] while honda gets leads = [0, 1, 2] and partners = [1, 2]. 45 | 46 | -- Solution 47 | select date_id,make_name, count(distinct lead_id) as unique_leads, 48 | count(distinct partner_id) as unique_partners 49 | from DailySales 50 | group by 1,2 -------------------------------------------------------------------------------- /easy/Primary Department For Each Employee Problem.sql: -------------------------------------------------------------------------------- 1 | -- Table Employees 2 | 3 | +---------------+---------+ 4 | | Column Name | Type | 5 | +---------------+---------+ 6 | | employee_id | int | 7 | | department_id | int | 8 | | primary_flag | varchar | 9 | +---------------+---------+ 10 | -- (employee_id, department_id) is the primary key for this table. 11 | -- employee_id is the id of the employee. 12 | -- department_id is the id of the department to which the employee belongs. 13 | -- primary_flag is an ENUM of type ('Y', 'N'). If the flag is 'Y', the department is the primary department for the employee. If the flag is 'N', the department is not the primary. 14 | 15 | -- 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’. 16 | -- Write an SQL query to report all the employees with their primary department. For employees who belong to one department, report their only department. 17 | -- Return the result table in any order. 18 | -- The query result format is in the following example. 19 | 20 | -- Employee table: 21 | +-------------+---------------+--------------+ 22 | | employee_id | department_id | primary_flag | 23 | +-------------+---------------+--------------+ 24 | | 1 | 1 | N | 25 | | 2 | 1 | Y | 26 | | 2 | 2 | N | 27 | | 3 | 3 | N | 28 | | 4 | 2 | N | 29 | | 4 | 3 | Y | 30 | | 4 | 4 | N | 31 | +-------------+---------------+--------------+ 32 | 33 | -- Result table: 34 | +-------------+---------------+ 35 | | employee_id | department_id | 36 | +-------------+---------------+ 37 | | 1 | 1 | 38 | | 2 | 1 | 39 | | 3 | 3 | 40 | | 4 | 3 | 41 | +-------------+---------------+ 42 | -- The Primary department for employee 1 is 1. 43 | -- The Primary department for employee 2 is 1. 44 | -- The Primary department for employee 3 is 3. 45 | -- The Primary department for employee 4 is 3. 46 | 47 | 48 | -- Solution 49 | select employee_id,department_id 50 | from employee_id 51 | where primary_flag ="Y" or employee_id in 52 | (select employee_id 53 | from Employee 54 | group by employee_id 55 | having count(department_id) =1) -------------------------------------------------------------------------------- /easy/Reported posts.sql: -------------------------------------------------------------------------------- 1 | -- Question 43 2 | -- Table: Actions 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | user_id | int | 8 | -- | post_id | int | 9 | -- | action_date | date | 10 | -- | action | enum | 11 | -- | extra | varchar | 12 | -- +---------------+---------+ 13 | 14 | -- There is no primary key for this table, it may have duplicate rows. 15 | -- The action column is an ENUM type of ('view', 'like', 'reaction', 'comment', 'report', 'share'). 16 | -- The extra column has optional information about the action such as a reason for report or a type of reaction. 17 | 18 | 19 | -- Write an SQL query that reports the number of posts reported yesterday for each report reason. Assume today is 2019-07-05. 20 | 21 | -- The query result format is in the following example: 22 | 23 | -- Actions table: 24 | -- +---------+---------+-------------+--------+--------+ 25 | -- | user_id | post_id | action_date | action | extra | 26 | -- +---------+---------+-------------+--------+--------+ 27 | -- | 1 | 1 | 2019-07-01 | view | null | 28 | -- | 1 | 1 | 2019-07-01 | like | null | 29 | -- | 1 | 1 | 2019-07-01 | share | null | 30 | -- | 2 | 4 | 2019-07-04 | view | null | 31 | -- | 2 | 4 | 2019-07-04 | report | spam | 32 | -- | 3 | 4 | 2019-07-04 | view | null | 33 | -- | 3 | 4 | 2019-07-04 | report | spam | 34 | -- | 4 | 3 | 2019-07-02 | view | null | 35 | -- | 4 | 3 | 2019-07-02 | report | spam | 36 | -- | 5 | 2 | 2019-07-04 | view | null | 37 | -- | 5 | 2 | 2019-07-04 | report | racism | 38 | -- | 5 | 5 | 2019-07-04 | view | null | 39 | -- | 5 | 5 | 2019-07-04 | report | racism | 40 | -- +---------+---------+-------------+--------+--------+ 41 | 42 | -- Result table: 43 | -- +---------------+--------------+ 44 | -- | report_reason | report_count | 45 | -- +---------------+--------------+ 46 | -- | spam | 1 | 47 | -- | racism | 2 | 48 | -- +---------------+--------------+ 49 | -- Note that we only care about report reasons with non zero number of reports. 50 | 51 | -- Solution 52 | Select extra as report_reason, count(distinct post_id) as report_count 53 | from actions 54 | group by extra 55 | where action = "report" 56 | and extra is not null 57 | and action_date = "2019-07-04" 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /easy/Sales Analysis 1.sql: -------------------------------------------------------------------------------- 1 | -- Question 27 2 | -- Table: Product 3 | 4 | -- +--------------+---------+ 5 | -- | Column Name | Type | 6 | -- +--------------+---------+ 7 | -- | product_id | int | 8 | -- | product_name | varchar | 9 | -- | unit_price | int | 10 | -- +--------------+---------+ 11 | -- product_id is the primary key of this table. 12 | -- Table: Sales 13 | 14 | -- +-------------+---------+ 15 | -- | Column Name | Type | 16 | -- +-------------+---------+ 17 | -- | seller_id | int | 18 | -- | product_id | int | 19 | -- | buyer_id | int | 20 | -- | sale_date | date | 21 | -- | quantity | int | 22 | -- | price | int | 23 | -- +------ ------+---------+ 24 | -- This table has no primary key, it can have repeated rows. 25 | -- product_id is a foreign key to Product table. 26 | 27 | 28 | -- Write an SQL query that reports the best seller by total sales price, If there is a tie, report them all. 29 | 30 | -- The query result format is in the following example: 31 | 32 | -- Product table: 33 | -- +------------+--------------+------------+ 34 | -- | product_id | product_name | unit_price | 35 | -- +------------+--------------+------------+ 36 | -- | 1 | S8 | 1000 | 37 | -- | 2 | G4 | 800 | 38 | -- | 3 | iPhone | 1400 | 39 | -- +------------+--------------+------------+ 40 | 41 | -- Sales table: 42 | -- +-----------+------------+----------+------------+----------+-------+ 43 | -- | seller_id | product_id | buyer_id | sale_date | quantity | price | 44 | -- +-----------+------------+----------+------------+----------+-------+ 45 | -- | 1 | 1 | 1 | 2019-01-21 | 2 | 2000 | 46 | -- | 1 | 2 | 2 | 2019-02-17 | 1 | 800 | 47 | -- | 2 | 2 | 3 | 2019-06-02 | 1 | 800 | 48 | -- | 3 | 3 | 4 | 2019-05-13 | 2 | 2800 | 49 | -- +-----------+------------+----------+------------+----------+-------+ 50 | 51 | -- Result table: 52 | -- +-------------+ 53 | -- | seller_id | 54 | -- +-------------+ 55 | -- | 1 | 56 | -- | 3 | 57 | -- +-------------+ 58 | -- Both sellers with id 1 and 3 sold products with the most total price of 2800. 59 | 60 | -- Solution 61 | select a.seller_id 62 | from 63 | (select s.seller_id, rank() over(order by sum(s.price) desc) as rk 64 | from product p 65 | inner join sales s 66 | on s.product_id = p.product_id 67 | group by s.seller_id) a 68 | where a.rk = 1 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /easy/Sales Analysis 3.sql: -------------------------------------------------------------------------------- 1 | -- Question 34 2 | -- Table: Product 3 | 4 | -- +--------------+---------+ 5 | -- | Column Name | Type | 6 | -- +--------------+---------+ 7 | -- | product_id | int | 8 | -- | product_name | varchar | 9 | -- | unit_price | int | 10 | -- +--------------+---------+ 11 | -- product_id is the primary key of this table. 12 | -- Table: Sales 13 | 14 | -- +-------------+---------+ 15 | -- | Column Name | Type | 16 | -- +-------------+---------+ 17 | -- | seller_id | int | 18 | -- | product_id | int | 19 | -- | buyer_id | int | 20 | -- | sale_date | date | 21 | -- | quantity | int | 22 | -- | price | int | 23 | -- +------ ------+---------+ 24 | -- This table has no primary key, it can have repeated rows. 25 | -- product_id is a foreign key to Product table. 26 | 27 | 28 | -- Write an SQL query that reports the products that were only sold in spring 2019. That is, between 2019-01-01 and 2019-03-31 inclusive. 29 | 30 | -- The query result format is in the following example: 31 | 32 | -- Product table: 33 | -- +------------+--------------+------------+ 34 | -- | product_id | product_name | unit_price | 35 | -- +------------+--------------+------------+ 36 | -- | 1 | S8 | 1000 | 37 | -- | 2 | G4 | 800 | 38 | -- | 3 | iPhone | 1400 | 39 | -- +------------+--------------+------------+ 40 | 41 | -- Sales table: 42 | -- +-----------+------------+----------+------------+----------+-------+ 43 | -- | seller_id | product_id | buyer_id | sale_date | quantity | price | 44 | -- +-----------+------------+----------+------------+----------+-------+ 45 | -- | 1 | 1 | 1 | 2019-01-21 | 2 | 2000 | 46 | -- | 1 | 2 | 2 | 2019-02-17 | 1 | 800 | 47 | -- | 2 | 2 | 3 | 2019-06-02 | 1 | 800 | 48 | -- | 3 | 3 | 4 | 2019-05-13 | 2 | 2800 | 49 | -- +-----------+------------+----------+------------+----------+-------+ 50 | 51 | -- Result table: 52 | -- +-------------+--------------+ 53 | -- | product_id | product_name | 54 | -- +-------------+--------------+ 55 | -- | 1 | S8 | 56 | -- +-------------+--------------+ 57 | -- The product with id 1 was only sold in spring 2019 while the other two were sold after. 58 | 59 | -- Solution 60 | 61 | 62 | select distinct p.product_id,p.product_name 63 | from product p 64 | inner join saless 65 | using(product_id) 66 | where s.ale_date between "2019-01-01" and "2019-03-31 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /hard/Average Salary: Departments VS Company.sql: -------------------------------------------------------------------------------- 1 | -- Question 108 2 | -- Given two tables as below, write a query to display the comparison result (higher/lower/same) of the 3 | -- average salary of employees in a department to the company's average salary. 4 | 5 | 6 | -- Table: salary 7 | -- | id | employee_id | amount | pay_date | 8 | -- |----|-------------|--------|------------| 9 | -- | 1 | 1 | 9000 | 2017-03-31 | 10 | -- | 2 | 2 | 6000 | 2017-03-31 | 11 | -- | 3 | 3 | 10000 | 2017-03-31 | 12 | -- | 4 | 1 | 7000 | 2017-02-28 | 13 | -- | 5 | 2 | 6000 | 2017-02-28 | 14 | -- | 6 | 3 | 8000 | 2017-02-28 | 15 | 16 | 17 | 18 | -- The employee_id column refers to the employee_id in the following table employee. 19 | 20 | 21 | -- | employee_id | department_id | 22 | -- |-------------|---------------| 23 | -- | 1 | 1 | 24 | -- | 2 | 2 | 25 | -- | 3 | 2 | 26 | 27 | 28 | -- So for the sample data above, the result is: 29 | 30 | 31 | -- | pay_month | department_id | comparison | 32 | -- |-----------|---------------|-------------| 33 | -- | 2017-03 | 1 | higher | 34 | -- | 2017-03 | 2 | lower | 35 | -- | 2017-02 | 1 | same | 36 | -- | 2017-02 | 2 | same | 37 | 38 | 39 | -- Explanation 40 | -- In March, the company's average salary is (9000+6000+10000)/3 = 8333.33... 41 | 42 | -- The average salary for department '1' is 9000, which is the salary of employee_id '1' since there is only one employee in this department. So the comparison result is 'higher' since 9000 > 8333.33 obviously. 43 | 44 | -- The average salary of department '2' is (6000 + 10000)/2 = 8000, which is the average of employee_id '2' and '3'. So the comparison result is 'lower' since 8000 < 8333.33. 45 | 46 | -- With the same formula for the average salary comparison in February, the result is 'same' since both the department '1' and '2' have the same average salary with the company, which is 7000. 47 | 48 | -- Solution 49 | with t1 as( 50 | select left(pay_date,7) as pay_month, department_id, 51 | avg(amount) over(partition by month(pay_date),department_id) as dept_avg, 52 | avg(amount) over(partition by month(pay_date)) as comp_avg 53 | from salary s 54 | join employee e 55 | using (employee_id)) 56 | 57 | select distinct pay_month, department_id, 58 | case when dept_avg > comp_avg then "higher" 59 | when dept_avg = comp_avg then "same" 60 | else "lower" end as comparison 61 | from t1 62 | order by pay_month desc 63 | -------------------------------------------------------------------------------- /medium/All people report to the given manager.sql: -------------------------------------------------------------------------------- 1 | -- Question 55 2 | -- Table: Employees 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | employee_id | int | 8 | -- | employee_name | varchar | 9 | -- | manager_id | int | 10 | -- +---------------+---------+ 11 | -- employee_id is the primary key for this table. 12 | -- Each row of this table indicates that the employee with ID employee_id and name employee_name reports his 13 | -- work to his/her direct manager with manager_id 14 | -- The head of the company is the employee with employee_id = 1. 15 | 16 | 17 | -- Write an SQL query to find employee_id of all employees that directly or indirectly report their work to the head of the company. 18 | 19 | -- The indirect relation between managers will not exceed 3 managers as the company is small. 20 | 21 | -- Return result table in any order without duplicates. 22 | 23 | -- The query result format is in the following example: 24 | 25 | -- Employees table: 26 | -- +-------------+---------------+------------+ 27 | -- | employee_id | employee_name | manager_id | 28 | -- +-------------+---------------+------------+ 29 | -- | 1 | Boss | 1 | 30 | -- | 3 | Alice | 3 | 31 | -- | 2 | Bob | 1 | 32 | -- | 4 | Daniel | 2 | 33 | -- | 7 | Luis | 4 | 34 | -- | 8 | Jhon | 3 | 35 | -- | 9 | Angela | 8 | 36 | -- | 77 | Robert | 1 | 37 | -- +-------------+---------------+------------+ 38 | 39 | -- Result table: 40 | -- +-------------+ 41 | -- | employee_id | 42 | -- +-------------+ 43 | -- | 2 | 44 | -- | 77 | 45 | -- | 4 | 46 | -- | 7 | 47 | -- +-------------+ 48 | 49 | -- The head of the company is the employee with employee_id 1. 50 | -- The employees with employee_id 2 and 77 report their work directly to the head of the company. 51 | -- The employee with employee_id 4 report his work indirectly to the head of the company 4 --> 2 --> 1. 52 | -- The employee with employee_id 7 report his work indirectly to the head of the company 7 --> 4 --> 2 --> 1. 53 | -- The employees with employee_id 3, 8 and 9 don't report their work to head of company directly or indirectly. 54 | 55 | 56 | -- Solution 57 | 58 | select 59 | from employees e1 60 | join employees e2 61 | join employees e3 62 | on e1.manager_id = e2.employee_id 63 | and e2.manager_id = e3.employee_id 64 | where e3.manager_id = 1 and e1.employee_id <> 1 -------------------------------------------------------------------------------- /easy/Students with invalid departments.sql: -------------------------------------------------------------------------------- 1 | -- Question 36 2 | -- Table: Departments 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | id | int | 8 | -- | name | varchar | 9 | -- +---------------+---------+ 10 | -- id is the primary key of this table. 11 | -- The table has information about the id of each department of a university. 12 | 13 | 14 | -- Table: Students 15 | 16 | -- +---------------+---------+ 17 | -- | Column Name | Type | 18 | -- +---------------+---------+ 19 | -- | id | int | 20 | -- | name | varchar | 21 | -- | department_id | int | 22 | -- +---------------+---------+ 23 | -- id is the primary key of this table. 24 | -- The table has information about the id of each student at a university and the id of the department he/she studies at. 25 | 26 | 27 | -- Write an SQL query to find the id and the name of all students who are enrolled in departments that no longer exists. 28 | 29 | -- Return the result table in any order. 30 | 31 | -- The query result format is in the following example: 32 | 33 | -- Departments table: 34 | -- +------+--------------------------+ 35 | -- | id | name | 36 | -- +------+--------------------------+ 37 | -- | 1 | Electrical Engineering | 38 | -- | 7 | Computer Engineering | 39 | -- | 13 | Bussiness Administration | 40 | -- +------+--------------------------+ 41 | 42 | -- Students table: 43 | -- +------+----------+---------------+ 44 | -- | id | name | department_id | 45 | -- +------+----------+---------------+ 46 | -- | 23 | Alice | 1 | 47 | -- | 1 | Bob | 7 | 48 | -- | 5 | Jennifer | 13 | 49 | -- | 2 | John | 14 | 50 | -- | 4 | Jasmine | 77 | 51 | -- | 3 | Steve | 74 | 52 | -- | 6 | Luis | 1 | 53 | -- | 8 | Jonathan | 7 | 54 | -- | 7 | Daiana | 33 | 55 | -- | 11 | Madelynn | 1 | 56 | -- +------+----------+---------------+ 57 | 58 | -- Result table: 59 | -- +------+----------+ 60 | -- | id | name | 61 | -- +------+----------+ 62 | -- | 2 | John | 63 | -- | 7 | Daiana | 64 | -- | 4 | Jasmine | 65 | -- | 3 | Steve | 66 | -- +------+----------+ 67 | 68 | -- John, Daiana, Steve and Jasmine are enrolled in departments 14, 33, 74 and 77 respectively. 69 | -- department 14, 33, 74 and 77 doesn't exist in the Departments table. 70 | 71 | -- Solution 72 | select id,name 73 | from students 74 | where department_id not in (select id from departments) 75 | -------------------------------------------------------------------------------- /easy/Ads performance.sql: -------------------------------------------------------------------------------- 1 | -- Question 13 2 | -- Table: Ads 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | ad_id | int | 8 | -- | user_id | int | 9 | -- | action | enum | 10 | -- +---------------+---------+ 11 | -- (ad_id, user_id) is the primary key for this table. 12 | -- Each row of this table contains the ID of an Ad, the ID of a user and the action taken by this user regarding this Ad. 13 | -- The action column is an ENUM type of ('Clicked', 'Viewed', 'Ignored'). 14 | 15 | 16 | -- A company is running Ads and wants to calculate the performance of each Ad. 17 | 18 | -- Performance of the Ad is measured using Click-Through Rate (CTR) where: 19 | 20 | 21 | 22 | -- Write an SQL query to find the ctr of each Ad. 23 | 24 | -- Round ctr to 2 decimal points. Order the result table by ctr in descending order and by ad_id in ascending order in case of a tie. 25 | 26 | -- The query result format is in the following example: 27 | 28 | -- Ads table: 29 | -- +-------+---------+---------+ 30 | -- | ad_id | user_id | action | 31 | -- +-------+---------+---------+ 32 | -- | 1 | 1 | Clicked | 33 | -- | 2 | 2 | Clicked | 34 | -- | 3 | 3 | Viewed | 35 | -- | 5 | 5 | Ignored | 36 | -- | 1 | 7 | Ignored | 37 | -- | 2 | 7 | Viewed | 38 | -- | 3 | 5 | Clicked | 39 | -- | 1 | 4 | Viewed | 40 | -- | 2 | 11 | Viewed | 41 | -- | 1 | 2 | Clicked | 42 | -- +-------+---------+---------+ 43 | -- Result table: 44 | -- +-------+-------+ 45 | -- | ad_id | ctr | 46 | -- +-------+-------+ 47 | -- | 1 | 66.67 | 48 | -- | 3 | 50.00 | 49 | -- | 2 | 33.33 | 50 | -- | 5 | 0.00 | 51 | -- +-------+-------+ 52 | -- for ad_id = 1, ctr = (2/(2+1)) * 100 = 66.67 53 | -- for ad_id = 2, ctr = (1/(1+2)) * 100 = 33.33 54 | -- for ad_id = 3, ctr = (1/(1+1)) * 100 = 50.00 55 | -- for ad_id = 5, ctr = 0.00, Note that ad_id = 5 has no clicks or views. 56 | -- Note that we don't care about Ignored Ads. 57 | -- Result table is ordered by the ctr. in case of a tie we order them by ad_id 58 | 59 | -- Solution 60 | with t1 as( 61 | select ad_id, sum(case when action in ('Clicked') then 1 else 0 end) as clicked 62 | from ads 63 | group by ad_id 64 | ) 65 | 66 | , t2 as 67 | ( 68 | Select ad_id as ad, sum(case when action in ('Clicked','Viewed') then 1 else 0 end) as total 69 | from ads 70 | group by ad_id 71 | ) 72 | 73 | Select a.ad_id,coalesce(round((clicked/total)*100,2),0) as ctr 74 | from 75 | ( 76 | select * 77 | from t1 join t2 78 | on t1.ad_id = t2.ad_id) a 79 | order by ctr desc, ad_id -------------------------------------------------------------------------------- /easy/Sales Person.sql: -------------------------------------------------------------------------------- 1 | -- Question 12 2 | -- Description 3 | -- Given three tables: salesperson, company, orders. 4 | -- Output all the names in the table salesperson, who didn’t have sales to company 'RED'. 5 | 6 | -- Example 7 | -- Input 8 | 9 | -- Table: salesperson 10 | 11 | -- +----------+------+--------+-----------------+-----------+ 12 | -- | sales_id | name | salary | commission_rate | hire_date | 13 | -- +----------+------+--------+-----------------+-----------+ 14 | -- | 1 | John | 100000 | 6 | 4/1/2006 | 15 | -- | 2 | Amy | 120000 | 5 | 5/1/2010 | 16 | -- | 3 | Mark | 65000 | 12 | 12/25/2008| 17 | -- | 4 | Pam | 25000 | 25 | 1/1/2005 | 18 | -- | 5 | Alex | 50000 | 10 | 2/3/2007 | 19 | -- +----------+------+--------+-----------------+-----------+ 20 | -- The table salesperson holds the salesperson information. Every salesperson has a sales_id and a name. 21 | -- Table: company 22 | 23 | -- +---------+--------+------------+ 24 | -- | com_id | name | city | 25 | -- +---------+--------+------------+ 26 | -- | 1 | RED | Boston | 27 | -- | 2 | ORANGE | New York | 28 | -- | 3 | YELLOW | Boston | 29 | -- | 4 | GREEN | Austin | 30 | -- +---------+--------+------------+ 31 | -- The table company holds the company information. Every company has a com_id and a name. 32 | -- Table: orders 33 | 34 | -- +----------+------------+---------+----------+--------+ 35 | -- | order_id | order_date | com_id | sales_id | amount | 36 | -- +----------+------------+---------+----------+--------+ 37 | -- | 1 | 1/1/2014 | 3 | 4 | 100000 | 38 | -- | 2 | 2/1/2014 | 4 | 5 | 5000 | 39 | -- | 3 | 3/1/2014 | 1 | 1 | 50000 | 40 | -- | 4 | 4/1/2014 | 1 | 4 | 25000 | 41 | -- +----------+----------+---------+----------+--------+ 42 | -- The table orders holds the sales record information, salesperson and customer company are represented by sales_id and com_id. 43 | -- output 44 | 45 | -- +------+ 46 | -- | name | 47 | -- +------+ 48 | -- | Amy | 49 | -- | Mark | 50 | -- | Alex | 51 | -- +------+ 52 | -- Explanation 53 | 54 | -- According to order '3' and '4' in table orders, it is easy to tell only salesperson 'John' and 'Pam' have sales to company 'RED', 55 | -- so we need to output all the other names in the table salesperson. 56 | 57 | -- Solution 58 | select name 59 | from salesperson 60 | where sales_id NOT IN (select distinct sales_id 61 | from orders 62 | where com_id = (select com_id 63 | from company 64 | where name = 'RED')) 65 | -------------------------------------------------------------------------------- /easy/Queries quality and percentage.sql: -------------------------------------------------------------------------------- 1 | -- Question 41 2 | -- Table: Queries 3 | 4 | -- +-------------+---------+ 5 | -- | Column Name | Type | 6 | -- +-------------+---------+ 7 | -- | query_name | varchar | 8 | -- | result | varchar | 9 | -- | position | int | 10 | -- | rating | int | 11 | -- +-------------+---------+ 12 | -- There is no primary key for this table, it may have duplicate rows. 13 | -- This table contains information collected from some queries on a database. 14 | -- The position column has a value from 1 to 500. 15 | -- The rating column has a value from 1 to 5. Query with rating less than 3 is a poor query. 16 | 17 | 18 | -- We define query quality as: 19 | 20 | -- The average of the ratio between query rating and its position. 21 | 22 | -- We also define poor query percentage as: 23 | 24 | -- The percentage of all queries with rating less than 3. 25 | 26 | -- Write an SQL query to find each query_name, the quality and poor_query_percentage. 27 | 28 | -- Both quality and poor_query_percentage should be rounded to 2 decimal places. 29 | 30 | -- The query result format is in the following example: 31 | 32 | -- Queries table: 33 | -- +------------+-------------------+----------+--------+ 34 | -- | query_name | result | position | rating | 35 | -- +------------+-------------------+----------+--------+ 36 | -- | Dog | Golden Retriever | 1 | 5 | 37 | -- | Dog | German Shepherd | 2 | 5 | 38 | -- | Dog | Mule | 200 | 1 | 39 | -- | Cat | Shirazi | 5 | 2 | 40 | -- | Cat | Siamese | 3 | 3 | 41 | -- | Cat | Sphynx | 7 | 4 | 42 | -- +------------+-------------------+----------+--------+ 43 | 44 | -- Result table: 45 | -- +------------+---------+-----------------------+ 46 | -- | query_name | quality | poor_query_percentage | 47 | -- +------------+---------+-----------------------+ 48 | -- | Dog | 2.50 | 33.33 | 49 | -- | Cat | 0.66 | 33.33 | 50 | -- +------------+---------+-----------------------+ 51 | 52 | -- Dog queries quality is ((5 / 1) + (5 / 2) + (1 / 200)) / 3 = 2.50 53 | -- Dog queries poor_ query_percentage is (1 / 3) * 100 = 33.33 54 | -- Cat queries quality equals ((2 / 5) + (3 / 3) + (4 / 7)) / 3 = 0.66 55 | -- Cat queries poor_ query_percentage is (1 / 3) * 100 = 33.33 56 | 57 | -- Solution 58 | select query_name, 59 | round(sum(rating/position)/count(query_name),2) as quality, 60 | round(avg(case when rating < 3 then 1 else 0 end )*100,2) as poor_query_percentage 61 | from queries 62 | group by query_name -------------------------------------------------------------------------------- /easy/Percentage of Users Attended a Contest.sql: -------------------------------------------------------------------------------- 1 | -- Table Users 2 | +-------------+---------+ 3 | | Column Name | Type | 4 | +-------------+---------+ 5 | | user_id | int | 6 | | user_name | varchar | 7 | +-------------+---------+ 8 | -- user_id is the primary key for this table. 9 | -- Each row of this table contains the name and the id of a user. 10 | 11 | -- Table Register 12 | 13 | +-------------+---------+ 14 | | Column Name | Type | 15 | +-------------+---------+ 16 | | contest_id | int | 17 | | user_id | int | 18 | +-------------+---------+ 19 | -- (contest_id, user_id) is the primary key for this table. 20 | -- Each row of this table contains the id of a user and the contest they registered into. 21 | 22 | -- Write an SQL query to find the percentage of the users registered in each contest rounded to two decimals. 23 | -- Return the result table ordered by percentage in descending order. In case of a tie, order it by contest_id in ascending order. 24 | -- The query result format is in the following example. 25 | 26 | -- Users table: 27 | +---------+-----------+ 28 | | user_id | user_name | 29 | +---------+-----------+ 30 | | 6 | Alice | 31 | | 2 | Bob | 32 | | 7 | Alex | 33 | +---------+-----------+ 34 | 35 | -- Register table: 36 | +------------+---------+ 37 | | contest_id | user_id | 38 | +------------+---------+ 39 | | 215 | 6 | 40 | | 209 | 2 | 41 | | 208 | 2 | 42 | | 210 | 6 | 43 | | 208 | 6 | 44 | | 209 | 7 | 45 | | 209 | 6 | 46 | | 215 | 7 | 47 | | 208 | 7 | 48 | | 210 | 2 | 49 | | 207 | 2 | 50 | | 210 | 7 | 51 | +------------+---------+ 52 | 53 | -- Result table: 54 | +------------+------------+ 55 | | contest_id | percentage | 56 | +------------+------------+ 57 | | 208 | 100.0 | 58 | | 209 | 100.0 | 59 | | 210 | 100.0 | 60 | | 215 | 66.67 | 61 | | 207 | 33.33 | 62 | +------------+------------+ 63 | -- All the users registered in contests 208, 209, and 210. The percentage is 100% and we sort them in the answer table by contest_id in ascending order. 64 | -- Alice and Alex registered in contest 215 and the percentage is ((2/3) * 100) = 66.67% 65 | -- Bob registered in contest 207 and the percentage is ((1/3) * 100) = 33.33% 66 | 67 | select r.contest_id as contest_id, 68 | round(count(distinct r.user_id)*100/count(distinct u.user_id),2) as percentage 69 | from users u 70 | inner join Register r 71 | on r.user_id =u.user_id 72 | group by r.contest_id 73 | order by percentage desc,contest_id -------------------------------------------------------------------------------- /medium/Activity Participants.sql: -------------------------------------------------------------------------------- 1 | -- Question 77 2 | -- Table: Friends 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | id | int | 8 | -- | name | varchar | 9 | -- | activity | varchar | 10 | -- +---------------+---------+ 11 | -- id is the id of the friend and primary key for this table. 12 | -- name is the name of the friend. 13 | -- activity is the name of the activity which the friend takes part in. 14 | -- Table: Activities 15 | 16 | -- +---------------+---------+ 17 | -- | Column Name | Type | 18 | -- +---------------+---------+ 19 | -- | id | int | 20 | -- | name | varchar | 21 | -- +---------------+---------+ 22 | -- id is the primary key for this table. 23 | -- name is the name of the activity. 24 | 25 | 26 | -- Write an SQL query to find the names of all the activities with neither maximum, nor minimum number of participants. 27 | 28 | -- Return the result table in any order. Each activity in table Activities is performed by any person in the table Friends. 29 | 30 | -- The query result format is in the following example: 31 | 32 | -- Friends table: 33 | -- +------+--------------+---------------+ 34 | -- | id | name | activity | 35 | -- +------+--------------+---------------+ 36 | -- | 1 | Jonathan D. | Eating | 37 | -- | 2 | Jade W. | Singing | 38 | -- | 3 | Victor J. | Singing | 39 | -- | 4 | Elvis Q. | Eating | 40 | -- | 5 | Daniel A. | Eating | 41 | -- | 6 | Bob B. | Horse Riding | 42 | -- +------+--------------+---------------+ 43 | 44 | -- Activities table: 45 | -- +------+--------------+ 46 | -- | id | name | 47 | -- +------+--------------+ 48 | -- | 1 | Eating | 49 | -- | 2 | Singing | 50 | -- | 3 | Horse Riding | 51 | -- +------+--------------+ 52 | 53 | -- Result table: 54 | -- +--------------+ 55 | -- | activity | 56 | -- +--------------+ 57 | -- | Singing | 58 | -- +--------------+ 59 | 60 | -- Eating activity is performed by 3 friends, maximum number of participants, (Jonathan D. , Elvis Q. and Daniel A.) 61 | -- Horse Riding activity is performed by 1 friend, minimum number of participants, (Bob B.) 62 | -- Singing is performed by 2 friends (Victor J. and Jade W.) 63 | 64 | 65 | 66 | -- Solution 67 | with participants_numbers as 68 | (select activity, count(activity) as total_friends 69 | from friends 70 | group by activity ) 71 | 72 | select activity from participants_numbers 73 | where total_friends not in 74 | (select max(total_friends),min(total_friends) 75 | from participants_numbers) 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /easy/User Activity for past 30 days 2.sql: -------------------------------------------------------------------------------- 1 | -- Question 35 2 | -- Table: Activity 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | user_id | int | 8 | -- | session_id | int | 9 | -- | activity_date | date | 10 | -- | activity_type | enum | 11 | -- +---------------+---------+ 12 | -- There is no primary key for this table, it may have duplicate rows. 13 | -- The activity_type column is an ENUM of type ('open_session', 'end_session', 'scroll_down', 'send_message'). 14 | -- The table shows the user activities for a social media website. 15 | -- Note that each session belongs to exactly one user. 16 | 17 | 18 | -- Write an SQL query to find the average number of sessions per user for a period of 30 days ending 2019-07-27 inclusively, rounded to 2 decimal places. The sessions we want to count for a user are those with at least one activity in that time period. 19 | 20 | -- The query result format is in the following example: 21 | 22 | -- Activity table: 23 | -- +---------+------------+---------------+---------------+ 24 | -- | user_id | session_id | activity_date | activity_type | 25 | -- +---------+------------+---------------+---------------+ 26 | -- | 1 | 1 | 2019-07-20 | open_session | 27 | -- | 1 | 1 | 2019-07-20 | scroll_down | 28 | -- | 1 | 1 | 2019-07-20 | end_session | 29 | -- | 2 | 4 | 2019-07-20 | open_session | 30 | -- | 2 | 4 | 2019-07-21 | send_message | 31 | -- | 2 | 4 | 2019-07-21 | end_session | 32 | -- | 3 | 2 | 2019-07-21 | open_session | 33 | -- | 3 | 2 | 2019-07-21 | send_message | 34 | -- | 3 | 2 | 2019-07-21 | end_session | 35 | -- | 3 | 5 | 2019-07-21 | open_session | 36 | -- | 3 | 5 | 2019-07-21 | scroll_down | 37 | -- | 3 | 5 | 2019-07-21 | end_session | 38 | -- | 4 | 3 | 2019-06-25 | open_session | 39 | -- | 4 | 3 | 2019-06-25 | end_session | 40 | -- +---------+------------+---------------+---------------+ 41 | 42 | -- Result table: 43 | -- +---------------------------+ 44 | -- | average_sessions_per_user | 45 | -- +---------------------------+ 46 | -- | 1.33 | 47 | -- +---------------------------+ 48 | -- User 1 and 2 each had 1 session in the past 30 days while user 3 had 2 sessions so the average is (1 + 1 + 2) / 3 = 1.33. 49 | 50 | 51 | -- Solution 52 | select round(avg(count(distinct session_id)),2) as average_sessions_per_user 53 | from activity 54 | where activity_date between "2019-06-26" and "2019-07-27" 55 | group by user_id 56 | -------------------------------------------------------------------------------- /easy/Bank Account Summary ||.sql: -------------------------------------------------------------------------------- 1 | -- Table users 2 | +--------------+---------+ 3 | | Column Name | Type | 4 | +--------------+---------+ 5 | | account | int | 6 | | name | varchar | 7 | +--------------+---------+ 8 | -- account is the primary key for this table. 9 | -- Each row of this table contains the account number of each user in the bank. 10 | 11 | -- Table Transactions 12 | 13 | +---------------+---------+ 14 | | Column Name | Type | 15 | +---------------+---------+ 16 | | trans_id | int | 17 | | account | int | 18 | | amount | int | 19 | | transacted_on | date | 20 | +---------------+---------+ 21 | -- trans_id is the primary key for this table. 22 | -- Each row of this table contains all changes made to all accounts. 23 | -- amount is positive if the user received money and negative if they transferred money. 24 | -- All accounts start with a balance 0. 25 | 26 | -- Write an SQL query to report the name and balance of users with a balance higher than 10000. The balance of an account is equal to the sum of the amounts of all transactions involving that account. 27 | --Return the result table in any order. 28 | --The query result format is in the following example 29 | 30 | -- Users table: 31 | +------------+--------------+ 32 | | account | name | 33 | +------------+--------------+ 34 | | 900001 | Alice | 35 | | 900002 | Bob | 36 | | 900003 | Charlie | 37 | +------------+--------------+ 38 | 39 | -- Transactions table: 40 | +------------+------------+------------+---------------+ 41 | | trans_id | account | amount | transacted_on | 42 | +------------+------------+------------+---------------+ 43 | | 1 | 900001 | 7000 | 2020-08-01 | 44 | | 2 | 900001 | 7000 | 2020-09-01 | 45 | | 3 | 900001 | -3000 | 2020-09-02 | 46 | | 4 | 900002 | 1000 | 2020-09-12 | 47 | | 5 | 900003 | 6000 | 2020-08-07 | 48 | | 6 | 900003 | 6000 | 2020-09-07 | 49 | | 7 | 900003 | -4000 | 2020-09-11 | 50 | +------------+------------+------------+---------------+ 51 | 52 | -- Result table: 53 | +------------+------------+ 54 | | name | balance | 55 | +------------+------------+ 56 | | Alice | 11000 | 57 | +------------+------------+ 58 | -- Alice's balance is (7000 + 7000 - 3000) = 11000. 59 | -- Bob's balance is 1000. 60 | -- Charlie's balance is (6000 + 6000 - 4000) = 8000. 61 | 62 | 63 | select a.name,a.balance 64 | (select u.name as name, 65 | sum(t.amount) as balance 66 | from users u 67 | inner join 68 | transactions t 69 | on t.account =u.account 70 | group by t.account) a 71 | where a.balance > 10000 -------------------------------------------------------------------------------- /easy/Reformat department table.sql: -------------------------------------------------------------------------------- 1 | -- Question 44 2 | -- Table: Department 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | id | int | 8 | -- | revenue | int | 9 | -- | month | varchar | 10 | -- +---------------+---------+ 11 | -- (id, month) is the primary key of this table. 12 | -- The table has information about the revenue of each department per month. 13 | -- The month has values in ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]. 14 | 15 | 16 | -- Write an SQL query to reformat the table such that there is a department id column and a revenue column for each month. 17 | 18 | -- The query result format is in the following example: 19 | 20 | -- Department table: 21 | -- +------+---------+-------+ 22 | -- | id | revenue | month | 23 | -- +------+---------+-------+ 24 | -- | 1 | 8000 | Jan | 25 | -- | 2 | 9000 | Jan | 26 | -- | 3 | 10000 | Feb | 27 | -- | 1 | 7000 | Feb | 28 | -- | 1 | 6000 | Mar | 29 | -- +------+---------+-------+ 30 | 31 | -- Result table: 32 | -- +------+-------------+-------------+-------------+-----+-------------+ 33 | -- | id | Jan_Revenue | Feb_Revenue | Mar_Revenue | ... | Dec_Revenue | 34 | -- +------+-------------+-------------+-------------+-----+-------------+ 35 | -- | 1 | 8000 | 7000 | 6000 | ... | null | 36 | -- | 2 | 9000 | null | null | ... | null | 37 | -- | 3 | null | 10000 | null | ... | null | 38 | -- +------+-------------+-------------+-------------+-----+-------------+ 39 | 40 | -- Note that the result table has 13 columns (1 for the department id + 12 for the months). 41 | 42 | 43 | -- Solution 44 | select id, 45 | sum(case when month="Jan" then revenue else null end ) as Jan_Revenue, 46 | sum(case when month ="Feb" then revenue else null end) as Feb_Revenue , 47 | sum(case when month ="Mar" then revenue else null end ) as Mar_Revenue, 48 | sum(case when month ="Apr" then revenue else null end) as Apr_Revenue, 49 | sum(case when month ="May" then revenue else null end) as May_Revenue, 50 | sum(case when month ="Jun" then revenue else null end) as Jun_Revenue, 51 | sum(case when month ="Jul" then revenue else null end) as Jul_Revenue, 52 | sum(case when month ="Aug" then revenue else null end) as Aug_Revenue, 53 | sum(case when month ="Sep" then revenue else null end) as Sep_Revenue, 54 | sum(case when month ="Oct" then revenue else null end) as Oct_Revenue, 55 | sum(case when month ="Nov" then revenue else null end) as Nov_Revenue, 56 | sum(case when month ="Dec" then revenue else null end) as Dec_Revenue 57 | from department 58 | group by id 59 | -------------------------------------------------------------------------------- /easy/Sales Analysis 2.sql: -------------------------------------------------------------------------------- 1 | -- Question 33 2 | -- Table: Product 3 | 4 | -- +--------------+---------+ 5 | -- | Column Name | Type | 6 | -- +--------------+---------+ 7 | -- | product_id | int | 8 | -- | product_name | varchar | 9 | -- | unit_price | int | 10 | -- +--------------+---------+ 11 | -- product_id is the primary key of this table. 12 | -- Table: Sales 13 | 14 | -- +-------------+---------+ 15 | -- | Column Name | Type | 16 | -- +-------------+---------+ 17 | -- | seller_id | int | 18 | -- | product_id | int | 19 | -- | buyer_id | int | 20 | -- | sale_date | date | 21 | -- | quantity | int | 22 | -- | price | int | 23 | -- +------ ------+---------+ 24 | -- This table has no primary key, it can have repeated rows. 25 | -- product_id is a foreign key to Product table. 26 | 27 | 28 | -- Write an SQL query that reports the buyers who have bought S8 but not iPhone. Note that S8 and iPhone are products present in the Product table. 29 | 30 | -- The query result format is in the following example: 31 | 32 | -- Product table: 33 | -- +------------+--------------+------------+ 34 | -- | product_id | product_name | unit_price | 35 | -- +------------+--------------+------------+ 36 | -- | 1 | S8 | 1000 | 37 | -- | 2 | G4 | 800 | 38 | -- | 3 | iPhone | 1400 | 39 | -- +------------+--------------+------------+ 40 | 41 | -- Sales table: 42 | -- +-----------+------------+----------+------------+----------+-------+ 43 | -- | seller_id | product_id | buyer_id | sale_date | quantity | price | 44 | -- +-----------+------------+----------+------------+----------+-------+ 45 | -- | 1 | 1 | 1 | 2019-01-21 | 2 | 2000 | 46 | -- | 1 | 2 | 2 | 2019-02-17 | 1 | 800 | 47 | -- | 2 | 1 | 3 | 2019-06-02 | 1 | 800 | 48 | -- | 3 | 3 | 3 | 2019-05-13 | 2 | 2800 | 49 | -- +-----------+------------+----------+------------+----------+-------+ 50 | 51 | -- Result table: 52 | -- +-------------+ 53 | -- | buyer_id | 54 | -- +-------------+ 55 | -- | 1 | 56 | -- +-------------+ 57 | -- The buyer with id 1 bought an S8 but didn't buy an iPhone. The buyer with id 3 bought both. 58 | 59 | -- Solution 60 | select distinct a.buyer_id 61 | (select a.buyer_id 62 | from product p 63 | inner join sales s 64 | using(product_id) 65 | ) a 66 | where a.buyer_id in (select buyer_id from product p inner join sales s using(product_id) where p.product_name= "S8") 67 | and a.buyer_id not in (select buyer_id from product p inner join sales s using(product_id) where p.product_name = "IPhone") 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /easy/Ad-Free Sessions.sql: -------------------------------------------------------------------------------- 1 | -- Table Playback 2 | 3 | +-------------+------+ 4 | | Column Name | Type | 5 | +-------------+------+ 6 | | session_id | int | 7 | | customer_id | int | 8 | | start_time | int | 9 | | end_time | int | 10 | +-------------+------+ 11 | -- session_id is the primary key for this table. 12 | -- customer_id is the ID of the customer watching this session. 13 | -- The session runs during the inclusive interval between start_time and end_time. 14 | -- It is guaranteed that start_time <= end_time and that two sessions for the same customer do not intersect. 15 | 16 | Table Ads 17 | 18 | +-------------+------+ 19 | | Column Name | Type | 20 | +-------------+------+ 21 | | ad_id | int | 22 | | customer_id | int | 23 | | timestamp | int | 24 | +-------------+------+ 25 | -- ad_id is the primary key for this table. 26 | -- customer_id is the ID of the customer viewing this ad. 27 | -- timestamp is the moment of time at which the ad was shown. 28 | 29 | -- Write an SQL query to report all the sessions that did not get shown any ads. 30 | -- Return the result table in any order. 31 | -- The query result format is in the following example: 32 | 33 | -- Playback table: 34 | +------------+-------------+------------+----------+ 35 | | session_id | customer_id | start_time | end_time | 36 | +------------+-------------+------------+----------+ 37 | | 1 | 1 | 1 | 5 | 38 | | 2 | 1 | 15 | 23 | 39 | | 3 | 2 | 10 | 12 | 40 | | 4 | 2 | 17 | 28 | 41 | | 5 | 2 | 2 | 8 | 42 | +------------+-------------+------------+----------+ 43 | 44 | -- Ads table: 45 | +-------+-------------+-----------+ 46 | | ad_id | customer_id | timestamp | 47 | +-------+-------------+-----------+ 48 | | 1 | 1 | 5 | 49 | | 2 | 2 | 17 | 50 | | 3 | 2 | 20 | 51 | +-------+-------------+-----------+ 52 | 53 | -- Result table: 54 | +------------+ 55 | | session_id | 56 | +------------+ 57 | | 2 | 58 | | 3 | 59 | | 5 | 60 | +------------+ 61 | -- The ad with ID 1 was shown to user 1 at time 5 while they were in session 1. 62 | -- The ad with ID 2 was shown to user 2 at time 17 while they were in session 4. 63 | -- The ad with ID 3 was shown to user 2 at time 20 while they were in session 4. 64 | -- We can see that sessions 1 and 4 had at least one ad. Sessions 2, 3, and 5 did not have any ads, so we return them. 65 | 66 | --Solution 67 | 68 | select session_id 69 | from Playback p 70 | left join 71 | Ads a 72 | on a.customer_id =p.customer_id 73 | and p.start_time <= a.timestamp 74 | and p.timestamp <= a.end_time 75 | where a.ad_id is null -------------------------------------------------------------------------------- /hard/Game Play Analysis 5.sql: -------------------------------------------------------------------------------- 1 | -- Question 111 2 | -- Table: Activity 3 | 4 | -- +--------------+---------+ 5 | -- | Column Name | Type | 6 | -- +--------------+---------+ 7 | -- | player_id | int | 8 | -- | device_id | int | 9 | -- | event_date | date | 10 | -- | games_played | int | 11 | -- +--------------+---------+ 12 | -- (player_id, event_date) is the primary key of this table. 13 | -- This table shows the activity of players of some game. 14 | -- Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device. 15 | 16 | 17 | -- We define the install date of a player to be the first login day of that player. 18 | 19 | -- We also define day 1 retention of some date X to be the number of players whose install date is X and they logged back in on the day right after X, divided by the number of players whose install date is X, rounded to 2 decimal places. 20 | 21 | -- Write an SQL query that reports for each install date, the number of players that installed the game on that day and the day 1 retention. 22 | 23 | -- The query result format is in the following example: 24 | 25 | -- Activity table: 26 | -- +-----------+-----------+------------+--------------+ 27 | -- | player_id | device_id | event_date | games_played | 28 | -- +-----------+-----------+------------+--------------+ 29 | -- | 1 | 2 | 2016-03-01 | 5 | 2 30 | -- | 1 | 2 | 2016-03-02 | 6 | 1 31 | -- | 2 | 3 | 2017-06-25 | 1 | 1 32 | -- | 3 | 1 | 2016-03-01 | 0 | 2 33 | -- | 3 | 4 | 2016-07-03 | 5 | 1 34 | -- +-----------+-----------+------------+--------------+ 35 | 36 | -- Result table: 37 | -- +------------+----------+----------------+ 38 | -- | install_dt | installs | Day1_retention | 39 | -- +------------+----------+----------------+ 40 | -- | 2016-03-01 | 2 | 0.50 | 41 | -- | 2017-06-25 | 1 | 0.00 | 42 | -- +------------+----------+----------------+ 43 | -- Player 1 and 3 installed the game on 2016-03-01 but only player 1 logged back in on 2016-03-02 so the 44 | -- day 1 retention of 2016-03-01 is 1 / 2 = 0.50 45 | -- Player 2 installed the game on 2017-06-25 but didn't log back in on 2017-06-26 so the day 1 retention of 2017-06-25 is 0 / 1 = 0.00 46 | 47 | 48 | -- Solution 49 | select distinct install_dt, count(distinct player_id) as installs, 50 | round(sum(case when next_day = install_dt+1 then 1 else 0 end)/count(distinct player_id),2) as Day1_retention 51 | from 52 | (select *,min(event_date) over(partition by player_id) as install_dt, 53 | lead(event_date) over(partition by player_id order by event_date) as next_day, 54 | row_number() over(partition by player order by event_date) as rk 55 | from activity 56 | ) a 57 | where rk =1 58 | group by 1 59 | order by 1 60 | -------------------------------------------------------------------------------- /medium/Grand Slam Titles.sql: -------------------------------------------------------------------------------- 1 | -- Table: Players 2 | +----------------+---------+ 3 | | Column Name | Type | 4 | +----------------+---------+ 5 | | player_id | int | 6 | | player_name | varchar | 7 | +----------------+---------+ 8 | --player_id is the primary key for this table. 9 | --Each row in this table contains the name and the ID of a tennis player. 10 | 11 | 12 | --Table: Championships 13 | +---------------+---------+ 14 | | Column Name | Type | 15 | +---------------+---------+ 16 | | year | int | 17 | | Wimbledon | int | 18 | | Fr_open | int | 19 | | US_open | int | 20 | | Au_open | int | 21 | +---------------+---------+ 22 | -- year is the primary key for this table. 23 | -- Each row of this table containts the IDs of the players who won one each tennis tournament of the grand slam. 24 | 25 | --Write an SQL query to report the number of grand slam tournaments won by each player. Do not include the players who did not win any tournament. 26 | --Return the result table in any order. 27 | --The query result format is in the following example: 28 | 29 | --Players table: 30 | +-----------+-------------+ 31 | | player_id | player_name | 32 | +-----------+-------------+ 33 | | 1 | Nadal | 34 | | 2 | Federer | 35 | | 3 | Novak | 36 | +-----------+-------------+ 37 | 38 | --Championships table: 39 | +------+-----------+---------+---------+---------+ 40 | | year | Wimbledon | Fr_open | US_open | Au_open | 41 | +------+-----------+---------+---------+---------+ 42 | | 2018 | 1 | 1 | 1 | 1 | 43 | | 2019 | 1 | 1 | 2 | 2 | 44 | | 2020 | 2 | 1 | 2 | 2 | 45 | +------+-----------+---------+---------+---------+ 46 | 47 | --Result table: 48 | +-----------+-------------+-------------------+ 49 | | player_id | player_name | grand_slams_count | 50 | +-----------+-------------+-------------------+ 51 | | 2 | Federer | 5 | 52 | | 1 | Nadal | 7 | 53 | +-----------+-------------+-------------------+ 54 | 55 | --Player 1 (Nadal) won 7 titles: Wimbledon (2018, 2019), Fr_open (2018, 2019, 2020), US_open (2018), and Au_open (2018). 56 | --Player 2 (Federer) won 5 titles: Wimbledon (2020), US_open (2019, 2020), and Au_open (2019, 2020). 57 | --Player 3 (Novak) did not win anything, we did not include them in the result table. 58 | 59 | -- Solution 60 | select p.player_id, p.player_name, 61 | sum( 62 | (case when c.Wimbledon = p.player_id then 1 else 0 end)+ 63 | (case when c.Fr_open = p.player_id then 1 else 0 end)+ 64 | (case when c.US_open = p.player_id then 1 else 0 end)+ 65 | (case when c.Au_open = p.player_id then 1 else 0 end) 66 | ) 67 | from players p 68 | join Championships c 69 | on c.Wimbledon =p.player_id or c.Fr_open =p.player_id or c.US_open = p.player_id or c.Au_open = p.player_id 70 | group by 1 71 | order by player_id desc 72 | 73 | -------------------------------------------------------------------------------- /easy/Top Travellers.sql: -------------------------------------------------------------------------------- 1 | -- Question 1 2 | -- Table: Users 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | id | int | 8 | -- | name | varchar | 9 | -- +---------------+---------+ 10 | -- id is the primary key for this table. 11 | -- name is the name of the user. 12 | 13 | 14 | -- Table: Rides 15 | 16 | -- +---------------+---------+ 17 | -- | Column Name | Type | 18 | -- +---------------+---------+ 19 | -- | id | int | 20 | -- | user_id | int | 21 | -- | distance | int | 22 | -- +---------------+---------+ 23 | -- id is the primary key for this table. 24 | -- user_id is the id of the user who travelled the distance "distance". 25 | 26 | 27 | -- Write an SQL query to report the distance travelled by each user. 28 | 29 | -- Return the result table ordered by travelled_distance in descending order, 30 | -- if two or more users travelled the same distance, order them by their name in ascending order. 31 | 32 | -- The query result format is in the following example. 33 | 34 | 35 | 36 | -- Users table: 37 | -- +------+-----------+ 38 | -- | id | name | 39 | -- +------+-----------+ 40 | -- | 1 | Alice | 41 | -- | 2 | Bob | 42 | -- | 3 | Alex | 43 | -- | 4 | Donald | 44 | -- | 7 | Lee | 45 | -- | 13 | Jonathan | 46 | -- | 19 | Elvis | 47 | -- +------+-----------+ 48 | 49 | -- Rides table: 50 | -- +------+----------+----------+ 51 | -- | id | user_id | distance | 52 | -- +------+----------+----------+ 53 | -- | 1 | 1 | 120 | 54 | -- | 2 | 2 | 317 | 55 | -- | 3 | 3 | 222 | 56 | -- | 4 | 7 | 100 | 57 | -- | 5 | 13 | 312 | 58 | -- | 6 | 19 | 50 | 59 | -- | 7 | 7 | 120 | 60 | -- | 8 | 19 | 400 | 61 | -- | 9 | 7 | 230 | 62 | -- +------+----------+----------+ 63 | 64 | -- Result table: 65 | -- +----------+--------------------+ 66 | -- | name | travelled_distance | 67 | -- +----------+--------------------+ 68 | -- | Elvis | 450 | 69 | -- | Lee | 450 | 70 | -- | Bob | 317 | 71 | -- | Jonathan | 312 | 72 | -- | Alex | 222 | 73 | -- | Alice | 120 | 74 | -- | Donald | 0 | 75 | -- +----------+--------------------+ 76 | -- Elvis and Lee travelled 450 miles, Elvis is the top traveller as his name is alphabetically smaller than Lee. 77 | -- Bob, Jonathan, Alex and Alice have only one ride and we just order them by the total distances of the ride. 78 | -- Donald didn't have any rides, the distance travelled by him is 0. 79 | 80 | 81 | 82 | -- Solution 83 | Select u.name as name, coalesce(sum(r.distance),0) as travelled_distance 84 | from users u 85 | left join rides 86 | on r.user_id =u.id 87 | group by u.name 88 | order by travelled_distance desc,u.name 89 | 90 | 91 | -------------------------------------------------------------------------------- /easy/Customer Who Visited but Did Not Make Any Transactions.sql: -------------------------------------------------------------------------------- 1 | -- Table Visits 2 | +-------------+---------+ 3 | | Column Name | Type | 4 | +-------------+---------+ 5 | | visit_id | int | 6 | | customer_id | int | 7 | +-------------+---------+ 8 | -- visit_id is the primary key for this table. 9 | -- This table contains information about the customers who visited the mall. 10 | 11 | -- Table Transactions 12 | +----------------+---------+ 13 | | Column Name | Type | 14 | +----------------+---------+ 15 | | transaction_id | int | 16 | | visit_id | int | 17 | | amount | int | 18 | +----------------+---------+ 19 | -- transaction_id is the primary key for this table. 20 | -- This table contains information about the transactions made during the visit_id. 21 | 22 | -- Write an SQL query to find the IDs of the users who visited without making any transactions and the number of times they made these types of visits. 23 | -- Return the result table sorted in any order. 24 | -- The query result format is in the following example: 25 | 26 | -- Visits 27 | +----------+-------------+ 28 | | visit_id | customer_id | 29 | +----------+-------------+ 30 | | 1 | 23 | 31 | | 2 | 9 | 32 | | 4 | 30 | 33 | | 5 | 54 | 34 | | 6 | 96 | 35 | | 7 | 54 | 36 | | 8 | 54 | 37 | +----------+-------------+ 38 | 39 | -- Transactions 40 | +----------------+----------+--------+ 41 | | transaction_id | visit_id | amount | 42 | +----------------+----------+--------+ 43 | | 2 | 5 | 310 | 44 | | 3 | 5 | 300 | 45 | | 9 | 5 | 200 | 46 | | 12 | 1 | 910 | 47 | | 13 | 2 | 970 | 48 | +----------------+----------+--------+ 49 | 50 | -- Result table: 51 | +-------------+----------------+ 52 | | customer_id | count_no_trans | 53 | +-------------+----------------+ 54 | | 54 | 2 | 55 | | 30 | 1 | 56 | | 96 | 1 | 57 | +-------------+----------------+ 58 | -- Customer with id = 23 visited the mall once and made one transaction during the visit with id = 12. 59 | -- Customer with id = 9 visited the mall once and made one transaction during the visit with id = 13. 60 | -- Customer with id = 30 visited the mall once and did not make any transactions. 61 | -- Customer with id = 54 visited the mall three times. During 2 visits they did not make any transactions, and during one visit they made 3 transactions. 62 | -- Customer with id = 96 visited the mall once and did not make any transactions. 63 | --As we can see, users with IDs 30 and 96 visited the mall one time without making any transactions. Also user 54 visited the mall twice and did not make any transactions. 64 | 65 | select customer_id, count(visit_id) as count_no_trans 66 | from visits where 67 | visit_id not in (select visit_id from transactions group by visit_id) 68 | group by customer_id 69 | -------------------------------------------------------------------------------- /medium/Group Employees of the Same Salary.sql: -------------------------------------------------------------------------------- 1 | -- Table : Employees 2 | +-------------+---------+ 3 | | Column Name | Type | 4 | +-------------+---------+ 5 | | employee_id | int | 6 | | name | varchar | 7 | | salary | int | 8 | +-------------+---------+ 9 | --employee_id is the primary key for this table. 10 | --Each row of this table indicates the employee ID, employee name, and salary. 11 | 12 | --A company wants to divide the employees into teams such that all the members on each team have the same salary. The teams should follow these criteria: 13 | 14 | --Each team should consist of at least two employees. 15 | --All the employees on a team should have the same salary. 16 | --All the employees of the same salary should be assigned to the same team. 17 | --If the salary of an employee is unique, we do not assign this employee to any team. 18 | --A team’s ID is assigned based on the rank of the team’s salary relative to the other teams’ salaries, where the team with the lowest salary has team_id = 1. Note that the salaries for employees not on a team are not included in this ranking. 19 | --Write an SQL query to get the team_id of each employee that is in a team. 20 | --Return the result table ordered by team_id in ascending order. In case of a tie, order it by employee_id in ascending order. 21 | --The query result format is in the following example: 22 | 23 | --Employees table: 24 | +-------------+---------+--------+ 25 | | employee_id | name | salary | 26 | +-------------+---------+--------+ 27 | | 2 | Meir | 3000 | 28 | | 3 | Michael | 3000 | 29 | | 7 | Addilyn | 7400 | 30 | | 8 | Juan | 6100 | 31 | | 9 | Kannon | 7400 | 32 | +-------------+---------+--------+ 33 | 34 | --Result table: 35 | +-------------+---------+--------+---------+ 36 | | employee_id | name | salary | team_id | 37 | +-------------+---------+--------+---------+ 38 | | 2 | Meir | 3000 | 1 | 39 | | 3 | Michael | 3000 | 1 | 40 | | 7 | Addilyn | 7400 | 2 | 41 | | 9 | Kannon | 7400 | 2 | 42 | +-------------+---------+--------+---------+ 43 | 44 | --Meir (employee_id=2) and Michael (employee_id=3) are in the same team because they have the same salary of 3000. 45 | --Addilyn (employee_id=7) and Kannon (employee_id=9) are in the same team because they have the same salary of 7400. 46 | --Juan (employee_id=8) is not included in any team because their salary of 6100 is unique (i.e. no other employee has the same salary). 47 | --The team IDs are assigned as follows (based on salary ranking, lowest first): 48 | - team_id=1: Meir and Michael, salary of 3000 49 | - team_id=2: Addilyn and Kannon, salary of 7400 50 | --Juan's salary of 6100 is not included in the ranking because they are not on a team. 51 | 52 | -- Solution 53 | select employee_id,name,salary,team_id 54 | from 55 | (select *, 56 | dense_rank() over(order by salary) as team_id 57 | from employees 58 | group by salary 59 | having count(*) >= 2) a 60 | order by team_id,employee_id 61 | 62 | -------------------------------------------------------------------------------- /easy/Average selling price.sql: -------------------------------------------------------------------------------- 1 | -- Question 39 2 | -- Table: Prices 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | product_id | int | 8 | -- | start_date | date | 9 | -- | end_date | date | 10 | -- | price | int | 11 | -- +---------------+---------+ 12 | -- (product_id, start_date, end_date) is the primary key for this table. 13 | -- Each row of this table indicates the price of the product_id in the period from start_date to end_date. 14 | -- For each product_id there will be no two overlapping periods. That means there will be no two intersecting periods for the same product_id. 15 | 16 | 17 | -- Table: UnitsSold 18 | 19 | -- +---------------+---------+ 20 | -- | Column Name | Type | 21 | -- +---------------+---------+ 22 | -- | product_id | int | 23 | -- | purchase_date | date | 24 | -- | units | int | 25 | -- +---------------+---------+ 26 | -- There is no primary key for this table, it may contain duplicates. 27 | -- Each row of this table indicates the date, units and product_id of each product sold. 28 | 29 | 30 | -- Write an SQL query to find the average selling price for each product. 31 | 32 | -- average_price should be rounded to 2 decimal places. 33 | 34 | -- The query result format is in the following example: 35 | 36 | -- Prices table: 37 | -- +------------+------------+------------+--------+ 38 | -- | product_id | start_date | end_date | price | 39 | -- +------------+------------+------------+--------+ 40 | -- | 1 | 2019-02-17 | 2019-02-28 | 5 | 41 | -- | 1 | 2019-03-01 | 2019-03-22 | 20 | 42 | -- | 2 | 2019-02-01 | 2019-02-20 | 15 | 43 | -- | 2 | 2019-02-21 | 2019-03-31 | 30 | 44 | -- +------------+------------+------------+--------+ 45 | 46 | -- UnitsSold table: 47 | -- +------------+---------------+-------+ 48 | -- | product_id | purchase_date | units | 49 | -- +------------+---------------+-------+ 50 | -- | 1 | 2019-02-25 | 100 | 51 | -- | 1 | 2019-03-01 | 15 | 52 | -- | 2 | 2019-02-10 | 200 | 53 | -- | 2 | 2019-03-22 | 30 | 54 | -- +------------+---------------+-------+ 55 | 56 | -- Result table: 57 | -- +------------+---------------+ 58 | -- | product_id | average_price | 59 | -- +------------+---------------+ 60 | -- | 1 | 6.96 | 61 | -- | 2 | 16.96 | 62 | -- +------------+---------------+ 63 | -- Average selling price = Total Price of Product / Number of products sold. 64 | -- Average selling price for product 1 = ((100 * 5) + (15 * 20)) / 115 = 6.96 65 | -- Average selling price for product 2 = ((200 * 15) + (30 * 30)) / 230 = 16.96 66 | 67 | 68 | -- Solution 69 | Select p.product_id, round(sum(p.price*u.units)/sum(u.units),2) as average_price 70 | from prices p 71 | join unitssold u 72 | where u.purchase_date between p.start_date and p.end_date 73 | group by p.product_id 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /medium/Count the Number of Experiments.sql: -------------------------------------------------------------------------------- 1 | -- Table: Experiments 2 | 3 | +-----------------+------+ 4 | | Column Name | Type | 5 | +-----------------+------+ 6 | | experiment_id | int | 7 | | platform | enum | 8 | | experiment_name | enum | 9 | +-----------------+------+ 10 | --experiment_id is the primary key for this table. 11 | --platform is an enum with one of the values ('Android', 'IOS', 'Web'). 12 | --experiment_name is an enum with one of the values ('Reading', 'Sports', 'Programming'). 13 | --This table contains information about the ID of an experiment done with a random person, the platform used to do the experiment, and the name of the experiment. 14 | 15 | 16 | --Write an SQL query to report the number of experiments done on each of the three platforms for each of the three given experiments. Notice that all the pairs of (platform, experiment) should be included in the output including the pairs with zero experiments. 17 | --Return the result table in any order. 18 | --The query result format is in the following example. 19 | --Example 1: 20 | 21 | --Input: 22 | --Experiments table: 23 | +---------------+----------+-----------------+ 24 | | experiment_id | platform | experiment_name | 25 | +---------------+----------+-----------------+ 26 | | 4 | IOS | Programming | 27 | | 13 | IOS | Sports | 28 | | 14 | Android | Reading | 29 | | 8 | Web | Reading | 30 | | 12 | Web | Reading | 31 | | 18 | Web | Programming | 32 | +---------------+----------+-----------------+ 33 | --Output: 34 | +----------+-----------------+-----------------+ 35 | | platform | experiment_name | num_experiments | 36 | +----------+-----------------+-----------------+ 37 | | Android | Reading | 1 | 38 | | Android | Sports | 0 | 39 | | Android | Programming | 0 | 40 | | IOS | Reading | 0 | 41 | | IOS | Sports | 1 | 42 | | IOS | Programming | 1 | 43 | | Web | Reading | 2 | 44 | | Web | Sports | 0 | 45 | | Web | Programming | 1 | 46 | +----------+-----------------+-----------------+ 47 | --Explanation: 48 | --On the platform "Android", we had only one "Reading" experiment. 49 | --On the platform "IOS", we had one "Sports" experiment and one "Programming" experiment. 50 | --On the platform "Web", we had two "Reading" experiments and one "Programming" experiment. 51 | 52 | --Solution 53 | select 54 | platform, 55 | experiment_name, 56 | coalesce(num_experiments, 0) as num_experiments 57 | from 58 | (select distinct platform from experiments) a 59 | cross join (select distinct experiment_name from experiments) b 60 | left join (select platform, experiment_name, count(*) as num_experiments 61 | from Experiments 62 | group by 1, 2) c 63 | using (platform, experiment_name) 64 | order by 1, 2 65 | -------------------------------------------------------------------------------- /easy/Number of comments per post.sql: -------------------------------------------------------------------------------- 1 | -- Question 31 2 | -- Table: Submissions 3 | 4 | -- +---------------+----------+ 5 | -- | Column Name | Type | 6 | -- +---------------+----------+ 7 | -- | sub_id | int | 8 | -- | parent_id | int | 9 | -- +---------------+----------+ 10 | -- There is no primary key for this table, it may have duplicate rows. 11 | -- Each row can be a post or comment on the post. 12 | -- parent_id is null for posts. 13 | -- parent_id for comments is sub_id for another post in the table. 14 | 15 | 16 | -- Write an SQL query to find number of comments per each post. 17 | 18 | -- Result table should contain post_id and its corresponding number_of_comments, 19 | -- and must be sorted by post_id in ascending order. 20 | 21 | -- Submissions may contain duplicate comments. You should count the number of unique comments per post. 22 | 23 | -- Submissions may contain duplicate posts. You should treat them as one post. 24 | 25 | -- The query result format is in the following example: 26 | 27 | -- Submissions table: 28 | 29 | -- +---------+------------+ 30 | -- | sub_id | parent_id | 31 | -- +---------+------------+ 32 | -- | 1 | Null | 33 | -- | 2 | Null | 1 null 3 1 34 | -- | 1 | Null | 35 | -- | 12 | Null | 36 | -- | 3 | 1 | 37 | -- | 5 | 2 | 38 | -- | 3 | 1 | 39 | -- | 4 | 1 | 40 | -- | 9 | 1 | 41 | -- | 10 | 2 | 42 | -- | 6 | 7 | 43 | 44 | 45 | -- +---------+------------+ 46 | -- | sub_id | parent_id | 47 | -- +---------+------------+ 48 | -- | 1 | Null | 49 | -- | 2 | Null | 50 | -- | 1 | Null | 51 | -- | 12 | Null | 52 | -- | 3 | 1 | 53 | -- | 5 | 2 | 54 | -- | 3 | 1 | 55 | -- | 4 | 1 | 56 | -- | 9 | 1 | 57 | -- | 10 | 2 | 58 | -- | 6 | 7 | 59 | 60 | -- Result table: 61 | -- +---------+--------------------+ 62 | -- | post_id | number_of_comments | 63 | -- +---------+--------------------+ 64 | -- | 1 | 3 | 65 | -- | 2 | 2 | 66 | -- | 12 | 0 | 67 | -- +---------+--------------------+ 68 | 69 | -- The post with id 1 has three comments in the table with id 3, 4 and 9. The comment with id 3 is 70 | -- repeated in the table, we counted it only once. 71 | -- The post with id 2 has two comments in the table with id 5 and 10. 72 | -- The post with id 12 has no comments in the table. 73 | -- The comment with id 6 is a comment on a deleted post with id 7 so we ignored it. 74 | 75 | -- Solution 76 | select s1.sub_id as post_id, 77 | count(distinct s2.sub_id) as number_of_comments 78 | from Submissions s1 79 | left join Submissions s2 80 | on s2.parent_id = s1.sub_id 81 | where s1.parent_id is null 82 | group by s1.sub_id 83 | 84 | -------------------------------------------------------------------------------- /hard/Find the Subtasks That Did Not Execute.sql: -------------------------------------------------------------------------------- 1 | --Table: Tasks 2 | +----------------+---------+ 3 | | Column Name | Type | 4 | +----------------+---------+ 5 | | task_id | int | 6 | | subtasks_count | int | 7 | +----------------+---------+ 8 | --task_id is the primary key for this table. 9 | --Each row in this table indicates that task_id was divided into subtasks_count subtasks labelled from 1 to subtasks_count. 10 | --It is guaranteed that 2 <= subtasks_count <= 20. 11 | 12 | --Table: Executed 13 | 14 | +---------------+---------+ 15 | | Column Name | Type | 16 | +---------------+---------+ 17 | | task_id | int | 18 | | subtask_id | int | 19 | +---------------+---------+ 20 | --(task_id, subtask_id) is the primary key for this table. 21 | --Each row in this table indicates that for the task task_id, the subtask with ID subtask_id was executed successfully. 22 | --It is guaranteed that subtask_id <= subtasks_count for each task_id. 23 | 24 | --Write an SQL query to report the IDs of the missing subtasks for each task_id. 25 | --Return the result table in any order. 26 | --The query result format is in the following example: 27 | 28 | --Tasks table: 29 | +---------+----------------+ 30 | | task_id | subtasks_count | 31 | +---------+----------------+ 32 | | 1 | 3 | 33 | | 2 | 2 | 34 | | 3 | 4 | 35 | +---------+----------------+ 36 | 37 | --Executed table: 38 | +---------+------------+ 39 | | task_id | subtask_id | 40 | +---------+------------+ 41 | | 1 | 2 | 42 | | 3 | 1 | 43 | | 3 | 2 | 44 | | 3 | 3 | 45 | | 3 | 4 | 46 | +---------+------------+ 47 | 48 | --Result table: 49 | +---------+------------+ 50 | | task_id | subtask_id | 51 | +---------+------------+ 52 | | 1 | 1 | 53 | | 1 | 3 | 54 | | 2 | 1 | 55 | | 2 | 2 | 56 | +---------+------------+ 57 | --Task 1 was divided into 3 subtasks (1, 2, 3). Only subtask 2 was executed successfully, so we include (1, 1) and (1, 3) in the answer. 58 | --Task 2 was divided into 2 subtasks (1, 2). No subtask was executed successfully, so we include (2, 1) and (2, 2) in the answer. 59 | --Task 3 was divided into 4 subtasks (1, 2, 3, 4). All of the subtasks were executed successfully. 60 | 61 | --Solution 62 | select t.task_id, x.subtask_id 63 | from Tasks t 64 | join ( 65 | select 1 as subtask_id union select 2 as subtask_id union select 3 as subtask_id union 66 | select 4 as subtask_id union select 5 as subtask_id union select 6 as subtask_id union 67 | select 10 as subtask_id union select 11 as subtask_id union select 12 as subtask_id union 68 | select 7 as subtask_id union select 8 as subtask_id union select 9 as subtask_id union 69 | select 13 as subtask_id union select 14 as subtask_id union select 15 as subtask_id union 70 | select 16 as subtask_id union select 17 as subtask_id union select 18 as subtask_id union 71 | select 19 as subtask_id union select 20 as subtask_id 72 | ) x 73 | where x.subtask_id <= t.subtasks_count and (t.task_id, x.subtask_id) not in ( 74 | select task_id, subtask_id from Executed 75 | ) 76 | -------------------------------------------------------------------------------- /medium/Evaluate Boolean Expressions.sql: -------------------------------------------------------------------------------- 1 | -- Question 78 2 | -- Table Variables: 3 | 4 | -- +---------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------+---------+ 7 | -- | name | varchar | 8 | -- | value | int | 9 | -- +---------------+---------+ 10 | -- name is the primary key for this table. 11 | -- This table contains the stored variables and their values. 12 | 13 | 14 | -- Table Expressions: 15 | 16 | -- +---------------+---------+ 17 | -- | Column Name | Type | 18 | -- +---------------+---------+ 19 | -- | left_operand | varchar | 20 | -- | operator | enum | 21 | -- | right_operand | varchar | 22 | -- +---------------+---------+ 23 | -- (left_operand, operator, right_operand) is the primary key for this table. 24 | -- This table contains a boolean expression that should be evaluated. 25 | -- operator is an enum that takes one of the values ('<', '>', '=') 26 | -- The values of left_operand and right_operand are guaranteed to be in the Variables table. 27 | 28 | 29 | -- Write an SQL query to evaluate the boolean expressions in Expressions table. 30 | 31 | -- Return the result table in any order. 32 | 33 | -- The query result format is in the following example. 34 | 35 | -- Variables table: 36 | -- +------+-------+ 37 | -- | name | value | 38 | -- +------+-------+ 39 | -- | x | 66 | 40 | -- | y | 77 | 41 | -- +------+-------+ 42 | 43 | -- Expressions table: 44 | -- +--------------+----------+---------------+ 45 | -- | left_operand | operator | right_operand | 46 | -- +--------------+----------+---------------+ 47 | -- | x | > | y | 48 | -- | x | < | y | 49 | -- | x | = | y | 50 | -- | y | > | x | 51 | -- | y | < | x | 52 | -- | x | = | x | 53 | -- +--------------+----------+---------------+ 54 | 55 | -- Result table: 56 | -- +--------------+----------+---------------+-------+ 57 | -- | left_operand | operator | right_operand | value | 58 | -- +--------------+----------+---------------+-------+ 59 | -- | x | > | y | false | 60 | -- | x | < | y | true | 61 | -- | x | = | y | false | 62 | -- | y | > | x | true | 63 | -- | y | < | x | false | 64 | -- | x | = | x | true | 65 | -- +--------------+----------+---------------+-------+ 66 | -- As shown, you need find the value of each boolean expression in the table using the variables table. 67 | 68 | -- Solution 69 | with t1 as( 70 | select e.left_operand, e.operator, e.right_operand, 71 | v.value as left_val, v_1.value as right_val 72 | from expressions e 73 | join variables v 74 | on v.name = e.left_operand 75 | join variables v_1 76 | on v_1.name = e.right_operand) 77 | 78 | select t1.left_operand, t1.operator, t1.right_operand, 79 | case when t1.operator = '<' then (select t1.left_val< t1.right_val) 80 | when t1.operator = '>' then (select t1.left_val > t1.right_val) 81 | when t1.operator = '=' then (select t1.left_val = t1.right_val) 82 | else FALSE 83 | end as value 84 | from t1 85 | -------------------------------------------------------------------------------- /medium/Confirmation Rate.sql: -------------------------------------------------------------------------------- 1 | -- Table: SignUp 2 | +----------------+----------+ 3 | | Column Name | Type | 4 | +----------------+----------+ 5 | | user_id | int | 6 | | time_stamp | datetime | 7 | +----------------+----------+ 8 | --user_id is the primary key for this table. 9 | --Each row contains information about the signup time for the user with ID user_id. 10 | 11 | -- Table: Confirmations 12 | +----------------+----------+ 13 | | Column Name | Type | 14 | +----------------+----------+ 15 | | user_id | int | 16 | | time_stamp | datetime | 17 | | action | ENUM | 18 | +----------------+----------+ 19 | --(user_id, time_stamp) is the primary key for this table. 20 | --user_id is a foreign key with a reference to the Signups table. 21 | --action is an ENUM of the type ('confirmed', 'timeout') 22 | --Each row of this table indicates that the user with ID user_id requested a confirmation message at time_stamp and that confirmation message was either confirmed ('confirmed') or expired without confirming ('timeout'). 23 | 24 | --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. 25 | --Write an SQL query to find the confirmation rate of each user. 26 | --Return the result table in any order. 27 | --The query result format is in the following example: 28 | 29 | --Signups table: 30 | +---------+---------------------+ 31 | | user_id | time_stamp | 32 | +---------+---------------------+ 33 | | 3 | 2020-03-21 10:16:13 | 34 | | 7 | 2020-01-04 13:57:59 | 35 | | 2 | 2020-07-29 23:09:44 | 36 | | 6 | 2020-12-09 10:39:37 | 37 | +---------+---------------------+ 38 | 39 | --Confirmations table: 40 | +---------+---------------------+-----------+ 41 | | user_id | time_stamp | action | 42 | +---------+---------------------+-----------+ 43 | | 3 | 2021-01-06 03:30:46 | timeout | 44 | | 3 | 2021-07-14 14:00:00 | timeout | 45 | | 7 | 2021-06-12 11:57:29 | confirmed | 46 | | 7 | 2021-06-13 12:58:28 | confirmed | 47 | | 7 | 2021-06-14 13:59:27 | confirmed | 48 | | 2 | 2021-01-22 00:00:00 | confirmed | 49 | | 2 | 2021-02-28 23:59:59 | timeout | 50 | +---------+---------------------+-----------+ 51 | 52 | --Result table 53 | +---------+-------------------+ 54 | | user_id | confirmation_rate | 55 | +---------+-------------------+ 56 | | 6 | 0.00 | 57 | | 3 | 0.00 | 58 | | 7 | 1.00 | 59 | | 2 | 0.50 | 60 | +---------+-------------------+ 61 | 62 | --User 6 did not request any confirmation messages. The confirmation rate is 0. 63 | --User 3 made 2 requests and both timed out. The confirmation rate is 0. 64 | --User 7 made 3 requests and all were confirmed. The confirmation rate is 1. 65 | --User 2 made 2 requests where one was confirmed and the other timed out. The confirmation rate is 1 / 2 = 0.5. 66 | 67 | --Solution 68 | select coalesce(round(sum(case when action="confirmed" then 1 else 0 end)*1.00 /count(*),2),0.0) as confirmation_rate 69 | from Signups s 70 | left join Confirmations c 71 | on c.user_id = s.user_id 72 | group by c.user_id -------------------------------------------------------------------------------- /easy/Product's Worth Over Invoices Problem.sql: -------------------------------------------------------------------------------- 1 | -- Table Product 2 | +-------------+---------+ 3 | | Column Name | Type | 4 | +-------------+---------+ 5 | | product_id | int | 6 | | name | varchar | 7 | +-------------+---------+ 8 | -- product_id is the primary key for this table. 9 | -- This table contains the ID and the name of the product. The name consists of only lowercase English letters. No two products have the same name. 10 | 11 | -- Table Invoice 12 | +-------------+------+ 13 | | Column Name | Type | 14 | +-------------+------+ 15 | | invoice_id | int | 16 | | product_id | int | 17 | | rest | int | 18 | | paid | int | 19 | | canceled | int | 20 | | refunded | int | 21 | +-------------+------+ 22 | -- invoice_id is the primary key for this table and the id of this invoice. 23 | -- product_id is the id of the product for this invoice. 24 | -- rest is the amount left to pay for this invoice. 25 | -- paid is the amount paid for this invoice. 26 | -- canceled is the amount canceled for this invoice. 27 | -- refunded is the amount refunded for this invoice. 28 | 29 | -- Write an SQL query that will, for all products, return each product name with total amount due, paid, canceled, and refunded across all invoices. 30 | -- Return the result table ordered by product_name. 31 | -- The query result format is in the following example: 32 | 33 | 34 | -- Product table: 35 | +------------+-------+ 36 | | product_id | name | 37 | +------------+-------+ 38 | | 0 | ham | 39 | | 1 | bacon | 40 | +------------+-------+ 41 | -- Invoice table: 42 | +------------+------------+------+------+----------+----------+ 43 | | invoice_id | product_id | rest | paid | canceled | refunded | 44 | +------------+------------+------+------+----------+----------+ 45 | | 23 | 0 | 2 | 0 | 5 | 0 | 46 | | 12 | 0 | 0 | 4 | 0 | 3 | 47 | | 1 | 1 | 1 | 1 | 0 | 1 | 48 | | 2 | 1 | 1 | 0 | 1 | 1 | 49 | | 3 | 1 | 0 | 1 | 1 | 1 | 50 | | 4 | 1 | 1 | 1 | 1 | 0 | 51 | +------------+------------+------+------+----------+----------+ 52 | -- Result table: 53 | +-------+------+------+----------+----------+ 54 | | name | rest | paid | canceled | refunded | 55 | +-------+------+------+----------+----------+ 56 | | bacon | 3 | 3 | 3 | 3 | 57 | | ham | 2 | 4 | 5 | 3 | 58 | +-------+------+------+----------+----------+ 59 | -- The amount of money left to pay for bacon is 1 + 1 + 0 + 1 = 3 60 | -- The amount of money paid for bacon is 1 + 0 + 1 + 1 = 3 61 | -- The amount of money canceled for bacon is 0 + 1 + 1 + 1 = 3 62 | -- The amount of money refunded for bacon is 1 + 1 + 1 + 0 = 3 63 | -- The amount of money left to pay for ham is 2 + 0 = 2 64 | -- The amount of money paid for ham is 0 + 4 = 4 65 | -- The amount of money canceled for ham is 5 + 0 = 5 66 | -- The amount of money refunded for ham is 0 + 3 = 3 67 | 68 | -- Solution 69 | select p.name as name,sum(i.rest) as rest, sum(i.paid) as paid, 70 | sum(i.canceled) as canceled,sum(i.refunded) as refunded 71 | from product p 72 | inner join invoice i 73 | on i.product_id = p.product_id 74 | group by 1 75 | order by 1 -------------------------------------------------------------------------------- /easy/Sellers with no sales.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Table Customers 3 | +---------------+---------+ 4 | | Column Name | Type | 5 | +---------------+---------+ 6 | | customer_id | int | 7 | | customer_name | varchar | 8 | +---------------+---------+ 9 | -- customer_id is the primary key for this table. 10 | -- Each row of this table contains the information of each customer in the WebStore. 11 | 12 | 13 | -- Table Orders 14 | +---------------+---------+ 15 | | Column Name | Type | 16 | +---------------+---------+ 17 | | order_id | int | 18 | | sale_date | date | 19 | | order_cost | int | 20 | | customer_id | int | 21 | | seller_id | int | 22 | +---------------+---------+ 23 | -- order_id is the primary key for this table. 24 | -- Each row of this table contains all orders made in the webstore. 25 | -- sale_date is the date when the transaction was made between the customer (customer_id) and the seller (seller_id). 26 | 27 | -- Table Sellers 28 | +---------------+---------+ 29 | | Column Name | Type | 30 | +---------------+---------+ 31 | | seller_id | int | 32 | | seller_name | varchar | 33 | +---------------+---------+ 34 | -- seller_id is the primary key for this table. 35 | -- Each row of this table contains the information of each seller. 36 | 37 | -- Write an SQL query to report the names of all sellers who did not make any sales in 2020. 38 | -- Return the result table ordered by seller_name in ascending order. 39 | -- The query result format is in the following example. 40 | 41 | -- Customer table: 42 | +--------------+---------------+ 43 | | customer_id | customer_name | 44 | +--------------+---------------+ 45 | | 101 | Alice | 46 | | 102 | Bob | 47 | | 103 | Charlie | 48 | +--------------+---------------+ 49 | 50 | -- Orders table: 51 | +-------------+------------+--------------+-------------+-------------+ 52 | | order_id | sale_date | order_cost | customer_id | seller_id | 53 | +-------------+------------+--------------+-------------+-------------+ 54 | | 1 | 2020-03-01 | 1500 | 101 | 1 | 55 | | 2 | 2020-05-25 | 2400 | 102 | 2 | 56 | | 3 | 2019-05-25 | 800 | 101 | 3 | 57 | | 4 | 2020-09-13 | 1000 | 103 | 2 | 58 | | 5 | 2019-02-11 | 700 | 101 | 2 | 59 | +-------------+------------+--------------+-------------+-------------+ 60 | 61 | -- Seller table: 62 | +-------------+-------------+ 63 | | seller_id | seller_name | 64 | +-------------+-------------+ 65 | | 1 | Daniel | 66 | | 2 | Elizabeth | 67 | | 3 | Frank | 68 | +-------------+-------------+ 69 | 70 | -- Result table: 71 | +-------------+ 72 | | seller_name | 73 | +-------------+ 74 | | Frank | 75 | +-------------+ 76 | -- Daniel made 1 sale in March 2020. 77 | -- Elizabeth made 2 sales in 2020 and 1 sale in 2019. 78 | -- Frank made 1 sale in 2019 but no sales in 2020. 79 | 80 | 81 | 82 | select a.seller_name as seller_name 83 | from seller s 84 | left join 85 | (select seller_id 86 | from orders 87 | where extract(year from sale_date) = 2020 88 | group by seller_id ) a 89 | on a.seller_id =s.seller_id 90 | where seller_id is null -------------------------------------------------------------------------------- /easy/Average Time of Process per Machine.sql: -------------------------------------------------------------------------------- 1 | -- Table Activity 2 | 3 | +----------------+---------+ 4 | | Column Name | Type | 5 | +----------------+---------+ 6 | | machine_id | int | 7 | | process_id | int | 8 | | activity_type | enum | 9 | | timestamp | float | 10 | +----------------+---------+ 11 | -- The table shows the user activities for a factory website. 12 | -- (machine_id, process_id, activity_type) is the primary key of this table. 13 | -- machine_id is the ID of a machine. 14 | -- process_id is the ID of a process running on the machine with ID machine_id. 15 | -- activity_type is an ENUM of type ('start', 'end'). 16 | -- timestamp is a float representing the current time in seconds. 17 | -- 'start' means the machine starts the process at the given timestamp and 'end' means the machine ends the process at the given timestamp. 18 | -- The 'start' timestamp will always be before the 'end' timestamp for every (machine_id, process_id) pair. 19 | 20 | -- There is a factory website that has several machines each running the same number of processes. 21 | -- Write an SQL query to find the average time each machine takes to complete a process. 22 | -- The time to complete a process is the ‘end’ timestamp minus the ‘start’ timestamp. The average time is calculated by the total time to complete every process on the machine divided by the number of processes that were run. 23 | -- The resulting table should have the machine_id along with the average time as processing_time, which should be rounded to 3 decimal places. 24 | -- The query result format is in the following example: 25 | 26 | 27 | -- Activity table: 28 | +------------+------------+---------------+-----------+ 29 | | machine_id | process_id | activity_type | timestamp | 30 | +------------+------------+---------------+-----------+ 31 | | 0 | 0 | start | 0.712 | 32 | | 0 | 0 | end | 1.520 | 33 | | 0 | 1 | start | 3.140 | 34 | | 0 | 1 | end | 4.120 | 35 | | 1 | 0 | start | 0.550 | 36 | | 1 | 0 | end | 1.550 | 37 | | 1 | 1 | start | 0.430 | 38 | | 1 | 1 | end | 1.420 | 39 | | 2 | 0 | start | 4.100 | 40 | | 2 | 0 | end | 4.512 | 41 | | 2 | 1 | start | 2.500 | 42 | | 2 | 1 | end | 5.000 | 43 | +------------+------------+---------------+-----------+ 44 | 45 | -- Result table: 46 | +------------+-----------------+ 47 | | machine_id | processing_time | 48 | +------------+-----------------+ 49 | | 0 | 0.894 | 50 | | 1 | 0.995 | 51 | | 2 | 1.456 | 52 | +------------+-----------------+ 53 | 54 | -- There are 3 machines running 2 processes each. 55 | -- Machine 0's average time is ((1.520 - 0.712) + (4.120 - 3.140)) / 2 = 0.894 56 | -- Machine 1's average time is ((1.550 - 0.550) + (1.420 - 0.430)) / 2 = 0.995 57 | -- Machine 2's average time is ((4.512 - 4.100) + (5.000 - 2.500)) / 2 = 1.456 58 | 59 | --Solution 60 | select machine_id, 61 | round(sum(case when activity_type="start" then -timestamp else timestamp)/count(distinct process_id),3) as processing_time 62 | from Activity 63 | group by 1 64 | order by 1 65 | -------------------------------------------------------------------------------- /easy/Warehouse Manager.sql: -------------------------------------------------------------------------------- 1 | -- Table warehouse 2 | +--------------+---------+ 3 | | Column Name | Type | 4 | +--------------+---------+ 5 | | name | varchar | 6 | | product_id | int | 7 | | units | int | 8 | +--------------+---------+ 9 | -- (name, product_id) is the primary key for this table. 10 | -- Each row of this table contains the information of the products in each warehouse. 11 | 12 | -- Table product 13 | +---------------+---------+ 14 | | Column Name | Type | 15 | +---------------+---------+ 16 | | product_id | int | 17 | | product_name | varchar | 18 | | Width | int | 19 | | Length | int | 20 | | Height | int | 21 | +---------------+---------+ 22 | -- product_id is the primary key for this table. 23 | -- Each row of this table contains the information about the product dimensions (Width, Lenght and Height) in feets of each product. 24 | 25 | -- Write an SQL query to report how much cubic feet of volume does the inventory occupy in each warehouse. 26 | -- warehouse_name 27 | -- volume Return the result table in any order. 28 | -- The query result format is in the following example. 29 | 30 | -- Warehouse table: 31 | +------------+--------------+-------------+ 32 | | name | product_id | units | 33 | +------------+--------------+-------------+ 34 | | LCHouse1 | 1 | 1 | 35 | | LCHouse1 | 2 | 10 | 36 | | LCHouse1 | 3 | 5 | 37 | | LCHouse2 | 1 | 2 | 38 | | LCHouse2 | 2 | 2 | 39 | | LCHouse3 | 4 | 1 | 40 | +------------+--------------+-------------+ 41 | 42 | -- Products table: 43 | +------------+--------------+------------+----------+-----------+ 44 | | product_id | product_name | Width | Length | Height | 45 | +------------+--------------+------------+----------+-----------+ 46 | | 1 | LC-TV | 5 | 50 | 40 | 47 | | 2 | LC-KeyChain | 5 | 5 | 5 | 48 | | 3 | LC-Phone | 2 | 10 | 10 | 49 | | 4 | LC-T-Shirt | 4 | 10 | 20 | 50 | +------------+--------------+------------+----------+-----------+ 51 | 52 | -- Result table: 53 | +----------------+------------+ 54 | | warehouse_name | volume | 55 | +----------------+------------+ 56 | | LCHouse1 | 12250 | 57 | | LCHouse2 | 20250 | 58 | | LCHouse3 | 800 | 59 | +----------------+------------+ 60 | 61 | -- Volume of product_id = 1 (LC-TV), 5x50x40 = 10000 62 | -- Volume of product_id = 2 (LC-KeyChain), 5x5x5 = 125 63 | -- Volume of product_id = 3 (LC-Phone), 2x10x10 = 200 64 | -- Volume of product_id = 4 (LC-T-Shirt), 4x10x20 = 800 65 | -- LCHouse1: 1 unit of LC-TV + 10 units of LC-KeyChain + 5 units of LC-Phone. 66 | -- Total volume: 1*10000 + 10*125 + 5*200 = 12250 cubic feet 67 | -- LCHouse2: 2 units of LC-TV + 2 units of LC-KeyChain. 68 | -- Total volume: 2*10000 + 2*125 = 20250 cubic feet 69 | -- LCHouse3: 1 unit of LC-T-Shirt. 70 | -- Total volume: 1*800 = 800 cubic feet. 71 | 72 | with product_volume as 73 | (select *, Width*Length*Height as volume 74 | from products) 75 | 76 | select w.name as warehouse_name, 77 | sum(s.units*pv.volume) as volume 78 | from warehouse w 79 | join product_volume pv 80 | on pv.product_id = w.product_id 81 | group by 1 82 | -------------------------------------------------------------------------------- /hard/Find the quiet students in the exam.sql: -------------------------------------------------------------------------------- 1 | -- Question 106 2 | -- Table: Student 3 | 4 | -- +---------------------+---------+ 5 | -- | Column Name | Type | 6 | -- +---------------------+---------+ 7 | -- | student_id | int | 8 | -- | student_name | varchar | 9 | -- +---------------------+---------+ 10 | -- student_id is the primary key for this table. 11 | -- student_name is the name of the student. 12 | 13 | 14 | -- Table: Exam 15 | 16 | -- +---------------+---------+ 17 | -- | Column Name | Type | 18 | -- +---------------+---------+ 19 | -- | exam_id | int | 20 | -- | student_id | int | 21 | -- | score | int | 22 | -- +---------------+---------+ 23 | -- (exam_id, student_id) is the primary key for this table. 24 | -- Student with student_id got score points in exam with id exam_id. 25 | 26 | 27 | -- A "quite" student is the one who took at least one exam and didn't score neither the high score nor the low score. 28 | 29 | -- Write an SQL query to report the students (student_id, student_name) being "quiet" in ALL exams. 30 | 31 | -- Don't return the student who has never taken any exam. Return the result table ordered by student_id. 32 | 33 | -- The query result format is in the following example. 34 | 35 | 36 | 37 | -- Student table: 38 | -- +-------------+---------------+ 39 | -- | student_id | student_name | 40 | -- +-------------+---------------+ 41 | -- | 1 | Daniel | 42 | -- | 2 | Jade | 43 | -- | 3 | Stella | 44 | -- | 4 | Jonathan | 45 | -- | 5 | Will | 46 | -- +-------------+---------------+ 47 | 48 | -- Exam table: 49 | -- +------------+--------------+-----------+ 50 | -- | exam_id | student_id | score | 51 | -- +------------+--------------+-----------+ 52 | -- | 10 | 1 | 70 | 53 | -- | 10 | 2 | 80 | 54 | -- | 10 | 3 | 90 | 55 | -- | 20 | 1 | 80 | 56 | -- | 30 | 1 | 70 | 57 | -- | 30 | 3 | 80 | 58 | -- | 30 | 4 | 90 | 59 | -- | 40 | 1 | 60 | 60 | -- | 40 | 2 | 70 | 61 | -- | 40 | 4 | 80 | 62 | -- +------------+--------------+-----------+ 63 | 64 | -- Result table: 65 | -- +-------------+---------------+ 66 | -- | student_id | student_name | 67 | -- +-------------+---------------+ 68 | -- | 2 | Jade | 69 | -- +-------------+---------------+ 70 | 71 | -- For exam 1: Student 1 and 3 hold the lowest and high score respectively. 72 | -- For exam 2: Student 1 hold both highest and lowest score. 73 | -- For exam 3 and 4: Studnet 1 and 4 hold the lowest and high score respectively. 74 | -- Student 2 and 5 have never got the highest or lowest in any of the exam. 75 | -- Since student 5 is not taking any exam, he is excluded from the result. 76 | -- So, we only return the information of Student 2. 77 | 78 | -- Solution 79 | with t1 as( 80 | select student_id 81 | from 82 | (select *, 83 | min(score) over(partition by exam_id) as least, 84 | max(score) over(partition by exam_id) as most 85 | from exam) a 86 | where least = score or most = score) 87 | 88 | 89 | select distinct student_id, student_name 90 | from exam join student 91 | using (student_id) 92 | where student_id != all(select student_id from t1) 93 | order by 1 -------------------------------------------------------------------------------- /medium/Count Apples and Oranges.sql: -------------------------------------------------------------------------------- 1 | -- Table: Boxes 2 | 3 | +--------------+------+ 4 | | Column Name | Type | 5 | +--------------+------+ 6 | | box_id | int | 7 | | chest_id | int | 8 | | apple_count | int | 9 | | orange_count | int | 10 | +--------------+------+ 11 | -- box_id is the primary key for this table. 12 | -- chest_id is a foreign key of the chests table. 13 | --This table contains information about the boxes and the number of oranges and apples they contain. Each box may contain a chest, which also can contain oranges and apples. 14 | 15 | -- Table: Chests 16 | 17 | +--------------+------+ 18 | | Column Name | Type | 19 | +--------------+------+ 20 | | chest_id | int | 21 | | apple_count | int | 22 | | orange_count | int | 23 | +--------------+------+ 24 | --chest_id is the primary key for this table. 25 | --This table contains information about the chests we have, and the corresponding number if oranges and apples they contain. 26 | 27 | --Write an SQL query to count the number of Apples and oranges we have in the boxes. If a box contains a chest, you should also include the number of apples and oranges it has. 28 | --Return the result table in any order. 29 | --The query result format is in the following example: 30 | 31 | --Boxes table: 32 | +--------+----------+-------------+--------------+ 33 | | box_id | chest_id | apple_count | orange_count | 34 | +--------+----------+-------------+--------------+ 35 | | 2 | null | 6 | 15 | 36 | | 18 | 14 | 4 | 15 | 37 | | 19 | 3 | 8 | 4 | 38 | | 12 | 2 | 19 | 20 | 39 | | 20 | 6 | 12 | 9 | 40 | | 8 | 6 | 9 | 9 | 41 | | 3 | 14 | 16 | 7 | 42 | +--------+----------+-------------+--------------+ 43 | 44 | --Chests table: 45 | +----------+-------------+--------------+ 46 | | chest_id | apple_count | orange_count | 47 | +----------+-------------+--------------+ 48 | | 6 | 5 | 6 | 49 | | 14 | 20 | 10 | 50 | | 2 | 8 | 8 | 51 | | 3 | 19 | 4 | 52 | | 16 | 19 | 19 | 53 | +----------+-------------+--------------+ 54 | 55 | --Result table: 56 | +-------------+--------------+ 57 | | apple_count | orange_count | 58 | +-------------+--------------+ 59 | | 151 | 123 | 60 | +-------------+--------------+ 61 | --box 2 has 6 apples and 15 oranges. 62 | --box 18 has 4 + 20 (from the chest) = 24 apples and 15 + 10 (from the chest) = 25 oranges. 63 | --box 19 has 8 + 19 (from the chest) = 27 apples and 4 + 4 (from the chest) = 8 oranges. 64 | --box 12 has 19 + 8 (from the chest) = 27 apples and 20 + 8 (from the chest) = 28 oranges. 65 | --box 20 has 12 + 5 (from the chest) = 17 apples and 9 + 6 (from the chest) = 15 oranges. 66 | --box 8 has 9 + 5 (from the chest) = 14 apples and 9 + 6 (from the chest) = 15 oranges. 67 | --box 3 has 16 + 20 (from the chest) = 36 apples and 7 + 10 (from the chest) = 17 oranges. 68 | --Total number of apples = 6 + 24 + 27 + 27 + 17 + 14 + 36 = 151 69 | --Total number of apples = 15 + 25 + 8 + 28 + 15 + 15 + 17 = 123 70 | 71 | --Solution 72 | select sum(b.apple_count + coalesce(c.apple_count,0)) as apple_count,sum(b.orange_count + coalesce(c.orange_count,0)) as orange_count 73 | from boxes b 74 | left join chests c 75 | on c.chest_id = b.chest_id 76 | group by b.chest_id -------------------------------------------------------------------------------- /medium/Find Cutoff Score for Each School.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Table: Schools 3 | +-------------+------+ 4 | | Column Name | Type | 5 | +-------------+------+ 6 | | school_id | int | 7 | | capacity | int | 8 | +-------------+------+ 9 | --school_id is the primary key for this table. 10 | --This table contains information about the capacity of some schools. The capacity is the maximum number of students the school can accept. 11 | 12 | -- Table: Exam 13 | +---------------+------+ 14 | | Column Name | Type | 15 | +---------------+------+ 16 | | score | int | 17 | | student_count | int | 18 | +---------------+------+ 19 | --score is the primary key for this table. 20 | --Each row in this table indicates that there are student_count students that got at least score points in the exam. 21 | --The data in this table will be logically correct, meaning a row recording a higher score will have the same or smaller student_count compared to a row recording a lower score. More formally, for every two rows i and j in the table, if scorei > scorej then student_counti <= student_countj 22 | 23 | --Every year, each school announces a minimum score requirement that a student needs to apply to it. The school chooses the minimum score requirement based on the exam results of all the students: 24 | --They want to ensure that even if every student meeting the requirement applies, the school can accept everyone. 25 | -- They also want to maximize the possible number of students that can apply. 26 | --They must use a score that is in the Exam table. 27 | --Write an SQL query to report the minimum score requirement for each school. If there are multiple score values satisfying the above conditions, choose the smallest one. If the input data is not enough to determine the score, report -1. 28 | --Return the result table in any order. 29 | --The query result format is in the following example. 30 | 31 | I--Input: 32 | --Schools table: 33 | +-----------+----------+ 34 | | school_id | capacity | 35 | +-----------+----------+ 36 | | 11 | 151 | 37 | | 5 | 48 | 38 | | 9 | 9 | 39 | | 10 | 99 | 40 | +-----------+----------+ 41 | --Exam table: 42 | +-------+---------------+ 43 | | score | student_count | 44 | +-------+---------------+ 45 | | 975 | 10 | 46 | | 966 | 60 | 47 | | 844 | 76 | 48 | | 749 | 76 | 49 | | 744 | 100 | 50 | +-------+---------------+ 51 | --Output: 52 | +-----------+-------+ 53 | | school_id | score | 54 | +-----------+-------+ 55 | | 5 | 975 | 56 | | 9 | -1 | 57 | | 10 | 749 | 58 | | 11 | 744 | 59 | +-----------+-------+ 60 | --Explanation: 61 | -- School 5: The school's capacity is 48. Choosing 975 as the min score requirement, the school will get at most 10 applications, which is within capacity. 62 | -- School 10: The school's capacity is 99. Choosing 844 or 749 as the min score requirement, the school will get at most 76 applications, which is within capacity. We choose the smallest of them, which is 749. 63 | -- School 11: The school's capacity is 151. Choosing 744 as the min score requirement, the school will get at most 100 applications, which is within capacity. 64 | -- School 9: The data given is not enough to determine the min score requirement. Choosing 975 as the min score, the school may get 10 requests while its capacity is 9. We do not have information about higher scores, hence we report -1. 65 | 66 | -- Solution 67 | select s.school_id,coalesce(min(score),-1) as score 68 | from Schools s left join Exam e 69 | on s.capacity >= e.student_count 70 | group by s.school_id; 71 | --------------------------------------------------------------------------------