tags: postgres, 02-lambdas-and-streams

1757. Recyclable and Low Fat Products Write a solution to find the ids of products that are both low fat and recyclable.

Input: products table
product_idlow_fatsrecyclable
0YN
1YY
2NY
3YY
4NN
Output
product_id
1
3
SELECT product_id FROM products
WHERE low_fats = 'Y' AND recyclable = 'Y';
products.stream()
	.filter(p -> p.low_fats == 'Y' && p.recyclable == 'Y')
	.map(p -> p.product_id)
	.collect(Collectors.toList());

584. Find Customer Referee Find the names of the customer that are either:

  1. referred by any customer with id != 2.
  2. not referred by any customer.
Input: customer table
idnamereferee_id
1Willnull
2Janenull
3Alex2
4Billnull
5Zack1
6Mark2
Output
name
Will
Jane
Bill
Zack
SELECT name FROM customer
WHERE referee_id != 2 OR referee_id IS NULL;
customer.stream()
	.filter(c -> c.referee_id == null || c.referee_id != 2)
	.map(c -> c.name)
	.collect(Collectors.toList());

595. Big Countries Write a solution to find the name, population, and area of the big countries. A country is big if:

  • it has an area of at least three million (i.e., 3000000 km2), or
  • it has a population of at least twenty-five million (i.e., 25000000).
Input: World table
namecontinentareapopulationgdp
AfghanistanAsia6522302550010020343000000
AlbaniaEurope28748283174112960000000
AlgeriaAfrica238174137100000188681000000
AndorraEurope468781153712000000
AngolaAfrica124670020609294100990000000
Output
namepopulationarea
Afghanistan25500100652230
Algeria371000002381741
SELECT name, population, area FROM world
WHERE area >= 3000000 OR population >= 25000000;
record WorldInfo(String name, long population, long area) {}
 
world.stream()
	.filter(w -> w.area >= 3000000 || w.population >= 25000000)
	.map(w -> new WorldInfo(w.name, w.population, w.area))
	.collect(Collectors.toList());

1148. Article Views I Write a solution to find all the authors that viewed at least one of their own articles. Return the result table sorted by id in ascending order.

Input: Views table
article_idauthor_idviewer_idview_date
1352019-08-01
1362019-08-02
2772019-08-01
2762019-08-02
4712019-07-22
3442019-07-21
3442019-07-21
Output
id
4
7
SELECT author_id as id FROM views
WHERE author_id = viewer_id
GROUP BY author_id
ORDER BY author_id
 
SELECT distinct author_id as id FROM views
WHERE aauthor_id = viewer_id
ORDER BY author_id
views.stream()
	.filter(v -> v.author_id == v.viewer_id)
	.collect(Collectors.groupingBy(v -> v.author_id))
	.keySet()
	.stream()
	.sorted()
	.collect(Collectors.toList());
	
views.stream()
	.filter(v -> v.author_id == v.viewer_id)
	.map(v -> v.author_id)
	.distinct()
	.sorted()
	.collect(Collectors.toList());

1683. Invalid Tweets Write a solution to find the IDs of the invalid tweets. The tweet is invalid if the number of characters used in the content of the tweet is strictly greater than 15.

Input: Tweets table
tweet_idcontent
1Let us Code
2More than fifteen chars are here!
Output
tweet_id
2
SELECT tweet_id FROM tweets
WHERE LENGTH(content) > 15;
tweets.stream()
	.filter(t -> t.length() > 15)
	.map(t -> t.tweet_id)
	.collect(Collectors.toList());

1378. Replace Employee ID With The Unique Identifier Write a solution to show the unique ID of each user, If a user does not have a unique ID replace just show null.

Input: Employees table
idname
1Alice
7Bob
11Meir
90Winston
3Jonathan
Input: EmployeeUNI table
idunique_id
31
112
903
Output
unique_idname
nullAlice
nullBob
2Meir
3Winston
1Jonathan
SELECT unique_id, name FROM employees e
LEFT JOIN employeeuni eu ON e.id = eu.id;
record EmployeeJoin(Integer uniqueId, String name) {}
 
Map<Integer, Integer> euMap = employeeUni.stream()
    .collect(Collectors.toMap(eu -> eu.id, eu.unique_id);
 
List<EmployeeJoin> result = employees.stream()
    .map(e -> new EmployeeJoin(euMap.get(e.id), e.name)
    .toList();

1068. Product Sales Analysis I Write a solution to report the product_nameyear, and price for each sale_id in the Sales table.

Input: Sales table
sale_idproduct_idyearquantityprice
11002008105000
21002009125000
72002011159000
Input: Product table
product_idproduct_name
100Nokia
200Apple
300Samsung
Output
product_nameyearprice
Nokia20085000
Nokia20095000
Apple20119000
SELECT product_name, year, price FROM sales s
JOIN product p ON p.product_id = s.product_id

1581. Customer Who Visited but Did Not Make Any Transactions Write a solution to find the IDs of the users who visited without making any transactions and the number of times they made these types of visits.

Input: Visits table
visit_idcustomer_id
123
29
430
554
696
754
854
Input: Transactions table
transaction_idvisit_idamount
25310
35300
95200
121910
132970
Output
customer_idcount_no_trans
542
301
961
SELECT customer_id, COUNT(*) AS count_no_trans FROM visits v
WHERE NOT EXISTS(
    SELECT t.visit_id FROM transactions t
    WHERE t.visit_id = v.visit_id
)
GROUP BY customer_id;
 
SELECT customer_id, count(*) AS count_no_trans FROM visits v
LEFT JOIN transactions t ON v.visit_id = t.visit_id
WHERE transaction_id IS NULL
GROUP BY customer_id;

197. Rising Temperature Write a solution to find all dates’ id with higher temperatures compared to its previous dates (yesterday).

Input: Weather table
idrecordDatetemperature
12015-01-0110
22015-01-0225
32015-01-0320
42015-01-0430
Output
id
2
4
SELECT w1.id FROM weather w1
JOIN weather w2 on w1.recorddate = w2.recorddate + INTERVAL '1 day'
WHERE w1.temperature > w2.temperature;
 
SELECT w1.id FROM weather w1
CROSS JOIN weather w2
WHERE w1.recorddate - w2.recorddate = 1
AND w1.temperature > w2.temperature

1661. Average Time of Process per Machine Write a solution to find the average time each machine takes to complete a process. Round the answer to 3 decimal places.

Input: Activity table
machine_idprocess_idactivity_typetimestamp
00start0.712
00end1.520
01start3.140
01end4.120
10start0.550
10end1.550
11start0.430
11end1.420
Output
machine_idprocessing_time
00.894
10.995
SELECT a1.machine_id, ROUND((SUM(a2.timestamp - a1.timestamp) / COUNT(*))::numeric, 3) AS processing_time
FROM activity a1
JOIN activity a2 ON a1.activity_type = 'start' AND a2.activity_type = 'end'
AND a1.machine_id = a2.machine_id AND a1.process_id = a2.process_id
GROUP BY a1.machine_id;
 
SELECT a1.machine_id, ROUND(AVG(a2.timestamp - a1.timestamp)::numeric, 3) AS processing_time
FROM activity a1
JOIN activity a2 ON a1.activity_type = 'start' AND a2.activity_type = 'end'
AND a1.machine_id = a2.machine_id AND a1.process_id = a2.process_id
GROUP BY a1.machine_id;

577. Employee Bonus Write a solution to report the name and bonus amount of each employee with a bonus less than 1000.

Input: Employee table
empIdnamesupervisorsalary
3Bradnull4000
1John31000
2Dan32000
4Thomas34000
Input: Bonus table
empIdbonus
2500
42000
Output
namebonus
Bradnull
Johnnull
Dan500
SELECT name, bonus FROM employee e
LEFT JOIN bonus b ON e.empid = b.empid
WHERE bonus IS NULL OR bonus < 1000;

1280. Students and Examinations Write a solution to find the number of times each student attended each exam. Return the result table ordered by student_id and subject_name.

Input: Students table
student_idstudent_name
1Alice
2Bob
13John
6Alex

Input: Examinations table
student_idsubject_name
1Math
1Physics
1Programming
2Programming
1Physics
1Math
13Math
13Programming
13Physics
2Math
1Math
Input: Subjects table
subject_name
Math
Physics
Programming

Output
student_idstudent_namesubject_nameattended_exams
1AliceMath3
1AlicePhysics2
1AliceProgramming1
2BobMath1
2BobPhysics0
2BobProgramming1
6AlexMath0
6AlexPhysics0
6AlexProgramming0
13JohnMath1
13JohnPhysics1
13JohnProgramming1
SELECT s.student_id, student_name, sub.subject_name, count(e) AS attended_exams FROM students s 
CROSS JOIN subjects sub 
LEFT JOIN examinations e ON s.student_id = e.student_id AND sub.subject_name = e.subject_name 
GROUP BY s.student_id, student_name, sub.subject_name
ORDER BY s.student_id, sub.subject_name;

570. Managers with at Least 5 Direct Reports Write a solution to find managers with at least five direct reports.

Input: Employee table
idnamedepartmentmanagerId
101JohnAnull
102DanA101
103JamesA101
104AmyA101
105AnneA101
106RonB101
Output
name
John
SELECT m.name FROM Employee m 
JOIN Employee e ON m.id = e.managerId 
GROUP BY m.id, m.name HAVING COUNT(1) >= 5;

1934. Confirmation Rate Write a solution to find the confirmation rate of each user. Round to two decimal places. The confirmation rate is the number of ‘confirmed’ messages divided by the total number of requested confirmation messages.

Input: Signups table
user_idtime_stamp
32020-03-21 10:16:13
72020-01-04 13:57:59
22020-07-29 23:09:44
62020-12-09 10:39:37
Input: Confirmations table
user_idtime_stampaction
32021-01-06 03:30:46timeout
32021-07-14 14:00:00timeout
72021-06-12 11:57:29confirmed
72021-06-13 12:58:28confirmed
72021-06-14 13:59:27confirmed
22021-01-22 00:00:00confirmed
22021-02-28 23:59:59timeout
Output
user_idconfirmation_rate
60.00
30.00
71.00
20.50
SELECT s.user_id,
ROUND(AVG(CASE WHEN c.action = 'confirmed' THEN 1 ELSE 0 END), 2) as confirmation_rate
FROM signups s
LEFT JOIN confirmations c on s.user_id = c.user_id
GROUP BY s.user_id

620. Not Boring Movies

Write a solution to report the movies with an odd-numbered ID and a description that is not “boring”. Return the result table ordered by rating in descending order.

Input: Cinema table
idmoviedescriptionrating
1Wargreat 3D8.9
2Sciencefiction8.5
3irishboring6.2
4Ice songFantacy8.6
5House cardInteresting9.1
Output
idmoviedescriptionrating
5House cardInteresting9.1
1Wargreat 3D8.9
SELECT * FROM cinema
WHERE description <> 'boring' AND id % 2 = 1
ORDER BY id DESC;

1251. Average Selling Price

Write a solution to find the average selling price for each product. Round to 2 decimal places. If a product does not have any sold units, its average price is 0.

Input: Prices table
product_idstart_dateend_dateprice
12019-02-172019-02-285
12019-03-012019-03-2220
22019-02-012019-02-2015
22019-02-212019-03-3130
Input: UnitsSold table
product_idpurchase_dateunits
12019-02-25100
12019-03-0115
22019-02-10200
22019-03-2230
Output
product_idaverage_price
16.96
216.96
SELECT p.product_id, COALESCE(ROUND(SUM(units * price)/SUM(units)::numeric, 2), 0) AS average_price
FROM prices p
LEFT JOIN unitssold u ON p.product_id = u.product_id
AND u.purchase_date BETWEEN p.start_date AND p.end_date
GROUP BY p.product_id;

1075. Project Employees I

Write a solution to report the average experience years of all the employees for each project, rounded to 2 digits.

Input: Project table
project_idemployee_id
11
12
13
21
24
Employee table
employee_idnameexperience_years
1Khaled3
2Ali2
3John1
4Doe2
Output
project_idaverage_years
12.00
22.50
SELECT p.project_id, ROUND(AVG(e.experience_years), 2) AS average_years 
FROM Project p 
JOIN Employee e ON p.employee_id = e.employee_id 
GROUP BY p.project_id;

1633. Percentage of Users Attended a Contest

Write a solution to find the percentage of the users registered in each contest rounded to two decimals. Return the result table ordered by percentage in descending order. In case of a tie, order by contest_id in ascending order.

Input: Users table
user_iduser_name
6Alice
2Bob
7Alex
Register table
contest_iduser_id
2156
2092
2082
2106
2086
2097
2096
2157
2087
2102
2072
2107
Output
contest_idpercentage
208100.00
209100.00
210100.00
21566.67
20733.33
SELECT r.contest_id, 
ROUND(COUNT(DISTINCT r.user_id)::numeric * 100 / (SELECT COUNT(*) FROM Users), 2) AS percentage
FROM Register r 
GROUP BY r.contest_id 
ORDER BY percentage DESC, r.contest_id;
WITH total AS (SELECT count(1) AS c from users)
 
SELECT contest_id,
ROUND(count(distinct user_id)::numeric * 100 / total.c, 2) as percentage
FROM register
CROSS JOIN total
GROUP BY contest_id, c
ORDER BY percentage desc, contest_id;

1211. Queries Quality and Percentage

Write a solution to find each query_name, the quality and poor_query_percentage. Both quality and poor_query_percentage should be rounded to 2 decimal places. Quality is the average of the ratio between query rating and position. A query is poor if its rating is less than 3.

Input: Queries table
query_nameresultpositionrating
DogGolden Retriever15
DogGerman Shepherd25
DogMule2001
CatShirazi52
CatSiamese33
CatSphynx74
Output
query_namequalitypoor_query_percentage
Dog2.5033.33
Cat0.6633.33
SELECT query_name, ROUND(AVG(rating::numeric / position), 2) AS quality,
ROUND(AVG(CASE WHEN rating < 3 THEN 1 ELSE 0 END)::numeric * 100, 2) AS poor_query_percentage
FROM queries
GROUP BY query_name;

1193. Monthly Transactions I

1193. Monthly Transactions I

Write a solution to find for each month and country, the number of transactions and their total amount, the number of approved transactions and their total amount.

Input: Transactions table
idcountrystateamounttrans_date
121USapproved10002018-12-18
122USdeclined20002018-12-19
123USapproved20002019-01-01
124DEapproved20002019-01-07
Output
monthcountrytrans_countapproved_counttrans_total_amountapproved_total_amount
2018-12US2130001000
2019-01US1120002000
2019-01DE1120002000
SELECT TO_CHAR(trans_date, 'YYYY-MM') AS month, country, count(*) AS trans_count,
SUM(CASE WHEN state = 'approved' THEN 1 ELSE 0 END) AS approved_count,
SUM(amount) AS trans_total_amount,
SUM(CASE WHEN state = 'approved' THEN amount ELSE 0 END) AS approved_total_amount
FROM transactions
GROUP BY month, country;

1174. Immediate Food Delivery II

1174. Immediate Food Delivery II

Write a solution to find the percentage of immediate orders in the first orders of all customers. Round to 2 decimal places. An order is immediate if the order date equals the customer preferred delivery date.

Input: Delivery table
delivery_idcustomer_idorder_datecustomer_pref_delivery_date
112019-08-012019-08-02
222019-08-022019-08-02
312019-08-112019-08-12
432019-08-242019-08-24
532019-08-212019-08-22
622019-08-112019-08-13
742019-08-092019-08-09
Output
immediate_percentage
50.00
SELECT ROUND(AVG(CASE WHEN order_date = customer_pref_delivery_date THEN 1 ELSE 0 END) * 100, 2) AS immediate_percentage
FROM delivery
WHERE (customer_id, order_date) IN (
    SELECT customer_id, MIN(order_date) AS first_order FROM delivery
    GROUP BY customer_id
)
WITH first_orders AS (
    SELECT customer_id, MIN(order_date) AS first_order_date FROM Delivery
    GROUP BY customer_id 
) 
 
SELECT ROUND(SUM(CASE WHEN d.order_date = d.customer_pref_delivery_date THEN 1 ELSE 0 END)::numeric * 100 / COUNT(*), 2) AS immediate_percentage 
FROM Delivery d 
JOIN first_orders f ON d.customer_id = f.customer_id  AND d.order_date = f.first_order_date;

550. Game Play Analysis IV

550. Game Play Analysis IV

Write a solution to report the fraction of players that logged in again on the day after the day they first logged in, rounded to 2 decimal places.

Input: Activity table
player_iddevice_idevent_dategames_played
122016-03-015
122016-03-026
232017-06-251
312016-03-020
342018-07-035
Output
fraction
0.33
WITH first_login AS (
    SELECT player_id, MIN(event_date) AS first_login_date FROM activity
    GROUP BY player_id
)
 
SELECT ROUND(COUNT(a2.player_id)::NUMERIC / COUNT(a1.player_id), 2) AS fraction
FROM first_login a1
LEFT JOIN activity a2 ON a1.player_id = a2.player_id
AND a1.first_login_date = a2.event_date - INTERVAL '1 day';

2356. Number of Unique Subjects Taught by Each Teacher

2356. Number of Unique Subjects Taught by Each Teacher

Write a solution to calculate the number of unique subjects each teacher teaches in the university.

Input: Teacher table
teacher_idsubject_iddept_id
123
124
133
211
221
231
241
Output
teacher_idcnt
12
24
SELECT teacher_id, COUNT(DISTINCT subject_id) AS cnt FROM teacher 
GROUP BY teacher_id;

1141. User Activity for the Past 30 Days I

1141. User Activity for the Past 30 Days I

Write a solution 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 they made at least one activity on that day.

Input: Activity table
user_idsession_idactivity_dateactivity_type
112019-07-20open_session
112019-07-20scroll_down
112019-07-20end_session
242019-07-20open_session
242019-07-21send_message
242019-07-21end_session
322019-07-21open_session
322019-07-21send_message
322019-07-21end_session
432019-06-25open_session
432019-06-25end_session
Output
dayactive_users
2019-07-202
2019-07-212
SELECT activity_date AS day, count(DISTINCT user_id) AS active_users FROM activity
WHERE activity_date BETWEEN '2019-07-27'::date - INTERVAL '29 DAYS' AND '2019-07-27'
GROUP BY activity_date;

1070. Product Sales Analysis III

1070. Product Sales Analysis III

Write a solution to select the product id, year, quantity, and price for the first year of every product sold.

Input: Sales table
sale_idproduct_idyearquantityprice
11002008105000
21002009125000
72002011159000
Product table
product_idproduct_name
100Nokia
200Apple
300Samsung
Output
product_idfirst_yearquantityprice
1002008105000
2002011159000
WITH first_year AS (
    SELECT product_id, MIN(year) as year FROM sales
    GROUP BY product_id
)
 
SELECT s.product_id, s.year AS first_year, s.quantity, s.price FROM sales s
JOIN first_year f ON s.product_id = f.product_id AND s.year = f.year;

596. Classes More Than 5 Students

596. Classes More Than 5 Students

Write a solution to find all the classes that have at least five students.

Input: Courses table
studentclass
AMath
BEnglish
CMath
DBiology
EMath
FComputer
GMath
HMath
IMath
Output
class
Math
SELECT class FROM courses
GROUP BY class HAVING COUNT(student) >= 5;
courses.stream()
	.collect(Collectors.groupingBy(course -> course.getClass(), Collectors.counting()))
	.entrySet().stream()
	.filter(entry -> entry.getValue() >= 5)
	.map(entry -> entry.getKey())
	.collect(Collectors.toList())

1729. Find Followers Count

1729. Find Followers Count

Write a solution that will, for each user, return the number of followers. Return the result table ordered by user_id in ascending order.

Input: Followers table
user_idfollower_id
01
10
20
21
Output
user_idfollowers_count
01
11
22
SELECT user_id, COUNT(*) AS followers_count FROM followers
GROUP BY user_id
ORDER BY user_id;

619. Biggest Single Number

619. Biggest Single Number

Write a solution to report the largest single number. If there is no single number, report null. A single number is a number that appeared only once.

Input: MyNumbers table
num
8
8
3
3
1
4
5
6
Output
num
6
SELECT MAX(num) AS num FROM (
    SELECT num FROM mynumbers
    GROUP BY num HAVING COUNT(*) = 1
)

1045. Customers Who Bought All Products

1045. Customers Who Bought All Products

Write a solution to report the customer ids that bought all the products in the Product table.

Input: Customer table
customer_idproduct_key
15
26
35
36
16
Product table
product_key
5
6
Output
customer_id
1
3
SELECT customer_id FROM Customer 
GROUP BY customer_id HAVING COUNT(DISTINCT product_key) = (SELECT COUNT(*) FROM Product);

1731. The Number of Employees Which Report to Each Employee

1731. The Number of Employees Which Report to Each Employee

Write a solution to report the ids and names of all managers, the number of employees who report directly to them, and the average age of the reports rounded to the nearest integer. Return the result table ordered by employee_id.

Input: Employees table
employee_idnamereports_toage
9Hercynull43
6Alice941
4Bob936
2Winstonnull37
Output
employee_idnamereports_countaverage_age
9Hercy239
SELECT e1.employee_id, e1.name, COUNT(*) AS reports_count, ROUND(AVG(e2.age)) AS average_age
FROM employees e1
JOIN employees e2 ON e1.employee_id = e2.reports_to
GROUP BY e1.employee_id, e1.name
ORDER BY e1.employee_id;

1789. Primary Department for Each Employee

1789. Primary Department for Each Employee

Write a solution to report all the employees with their primary department. For employees who belong to one department, report their only department.

Input: Employee table
employee_iddepartment_idprimary_flag
11N
21Y
22N
33N
42N
43Y
44N
Output
employee_iddepartment_id
11
21
33
43
SELECT employee_id, department_id FROM employee
WHERE primary_flag = 'Y'
UNION
SELECT employee_id, department_id FROM employee
WHERE employee_id IN (
    SELECT employee_id FROM employee
    GROUP BY employee_id HAVING COUNT(*) = 1
);
 
 
SELECT employee_id, department_id FROM employee
WHERE primary_flag = 'Y'
OR employee_id IN (
    SELECT employee_id FROM employee
    GROUP BY employee_id HAVING COUNT(*) = 1
);

610. Triangle Judgement

610. Triangle Judgement

Write a solution to report for every three line segments whether they can form a triangle.

Input: Triangle table
xyz
131530
102015
Output
xyztriangle
131530No
102015Yes
SELECT x, y, z,
CASE WHEN (x + y > z) AND (y + z > x) AND (z + x > y)
     THEN 'Yes'
     ELSE 'No'
END AS triangle FROM triangle

180. Consecutive Numbers

180. Consecutive Numbers

Write a solution to find all numbers that appear at least three times consecutively.

Input: Logs table
idnum
11
21
31
42
51
62
72
Output
ConsecutiveNums
1
SELECT DISTINCT l1.num AS consecutivenums FROM logs l1
JOIN logs l2 ON l1.id = l2.id - 1 AND l1.num = l2.num
JOIN logs l3 ON l2.id = l3.id - 1 AND l2.num = l3.num;

1164. Product Price at a Given Date

1164. Product Price at a Given Date

Write a solution to find the prices of all products on 2019-08-16. Assume the price of all products before any change is 10.

Input: Products table
product_idnew_pricechange_date
1202019-08-14
2502019-08-14
1302019-08-15
1352019-08-16
2652019-08-17
3202019-08-18
Output
product_idprice
250
135
310
WITH latest_prices AS (
	SELECT product_id, new_price, change_date,
	ROW_NUMBER() OVER (
		PARTITION BY product_id 
		ORDER BY change_date DESC
	) AS rn 
	FROM products 
	WHERE change_date <= '2019-08-16' 
) 
 
SELECT product_id, new_price AS price FROM latest_prices 
WHERE rn = 1 
UNION 
SELECT DISTINCT product_id, 10 AS price FROM products 
WHERE product_id NOT IN (
	SELECT product_id FROM products WHERE change_date <= '2019-08-16'
);
WITH unique_products AS (
    SELECT product_id , MAX(change_date) AS date FROM products
    WHERE change_date <= '2019-08-16'
    GROUP BY product_id
),
 
unique_prices AS (
    SELECT p.product_id, new_price AS price FROM products p 
    JOIN unique_products u 
    ON p.product_id = u.product_id AND p.change_date = u.date
)
 
SELECT DISTINCT p.product_id, COALESCE(price, 10) AS price FROM products p
LEFT JOIN unique_prices u 
ON p.product_id = u.product_id;