🧠
Correlated Subquery with EXISTS
💡 This approach uses a correlated subquery with EXISTS, which checks for the existence of matching rows for each outer row. It is more efficient in many SQL engines because it can short-circuit and stop searching once a match is found.
Intuition
For each customer, check if there exists at least one order with that customer's ID.
Algorithm
- For each customer in the outer query, run a subquery to check if any order exists with that customer's ID.
- If the subquery returns any row, EXISTS evaluates to true.
- Select customers where EXISTS is true.
- This query runs the subquery once per outer row but can be optimized by the database engine.
💡 Understanding that the subquery depends on the outer query row is key to grasping correlated subqueries.
def customers_with_orders_exists(customers, orders):
# Build a map from customer_id to orders for quick lookup
order_map = {}
for order in orders:
order_map.setdefault(order['customer_id'], []).append(order)
result = []
for c in customers:
if c['id'] in order_map:
result.append(c)
return result
# Example usage
if __name__ == '__main__':
customers = [{'id':1,'name':'Alice'},{'id':2,'name':'Bob'},{'id':3,'name':'Charlie'}]
orders = [{'order_id':101,'customer_id':1},{'order_id':102,'customer_id':2},{'order_id':103,'customer_id':2}]
res = customers_with_orders_exists(customers, orders)
print([c['name'] for c in res]) # ['Alice', 'Bob']
Line Notes
order_map = {}Prepares a dictionary to simulate quick lookup for correlated subquery
order_map.setdefault(order['customer_id'], []).append(order)Groups orders by customer_id to simulate EXISTS check
if c['id'] in order_mapChecks if any order exists for the current customer simulating EXISTS
result.append(c)Adds customer to result if condition is met
import java.util.*;
public class CorrelatedSubquery {
public static List<String> customersWithOrdersExists(List<Customer> customers, List<Order> orders) {
Map<Integer, List<Order>> orderMap = new HashMap<>();
for (Order o : orders) {
orderMap.computeIfAbsent(o.customerId, k -> new ArrayList<>()).add(o);
}
List<String> result = new ArrayList<>();
for (Customer c : customers) {
if (orderMap.containsKey(c.id)) {
result.add(c.name);
}
}
return result;
}
static class Customer {
int id; String name;
Customer(int id, String name) { this.id = id; this.name = name; }
}
static class Order {
int orderId, customerId;
Order(int orderId, int customerId) { this.orderId = orderId; this.customerId = customerId; }
}
public static void main(String[] args) {
List<Customer> customers = Arrays.asList(new Customer(1,"Alice"), new Customer(2,"Bob"), new Customer(3,"Charlie"));
List<Order> orders = Arrays.asList(new Order(101,1), new Order(102,2), new Order(103,2));
List<String> res = customersWithOrdersExists(customers, orders);
System.out.println(res); // [Alice, Bob]
}
}
Line Notes
Map<Integer, List<Order>> orderMap = new HashMap<>();Creates a map to group orders by customer ID for quick lookup
orderMap.computeIfAbsent(o.customerId, k -> new ArrayList<>()).add(o);Groups orders by customer ID simulating correlated subquery
if (orderMap.containsKey(c.id))Checks existence of orders for the customer simulating EXISTS
System.out.println(res);Outputs the result for verification
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
struct Customer {
int id; string name;
};
struct Order {
int order_id; int customer_id;
};
vector<string> customersWithOrdersExists(const vector<Customer>& customers, const vector<Order>& orders) {
unordered_map<int, vector<Order>> orderMap;
for (const auto& o : orders) {
orderMap[o.customer_id].push_back(o);
}
vector<string> result;
for (const auto& c : customers) {
if (orderMap.find(c.id) != orderMap.end()) {
result.push_back(c.name);
}
}
return result;
}
int main() {
vector<Customer> customers = {{1,"Alice"},{2,"Bob"},{3,"Charlie"}};
vector<Order> orders = {{101,1},{102,2},{103,2}};
vector<string> res = customersWithOrdersExists(customers, orders);
for (auto& name : res) cout << name << " ";
cout << endl; // Alice Bob
return 0;
}
Line Notes
unordered_map<int, vector<Order>> orderMap;Maps customer IDs to their orders for quick existence check
orderMap[o.customer_id].push_back(o);Groups orders by customer ID simulating correlated subquery
if (orderMap.find(c.id) != orderMap.end())Checks if any order exists for the customer simulating EXISTS
for (auto& name : res) cout << name << " ";Prints the result for verification
function customersWithOrdersExists(customers, orders) {
const orderMap = new Map();
for (const o of orders) {
if (!orderMap.has(o.customer_id)) orderMap.set(o.customer_id, []);
orderMap.get(o.customer_id).push(o);
}
return customers.filter(c => orderMap.has(c.id));
}
// Example usage
const customers = [{id:1,name:'Alice'},{id:2,name:'Bob'},{id:3,name:'Charlie'}];
const orders = [{order_id:101,customer_id:1},{order_id:102,customer_id:2},{order_id:103,customer_id:2}];
const res = customersWithOrdersExists(customers, orders);
console.log(res.map(c => c.name)); // ['Alice', 'Bob']
Line Notes
const orderMap = new Map();Creates a map to group orders by customer ID for quick lookup
orderMap.get(o.customer_id).push(o);Groups orders by customer ID simulating correlated subquery
return customers.filter(c => orderMap.has(c.id));Filters customers with at least one order simulating EXISTS
console.log(res.map(c => c.name));Prints the filtered customer names for verification
TimeO(n + m) where n = number of customers, m = number of orders
SpaceO(m) for the map storing orders by customer ID
We build a map from orders and then check existence per customer, similar to approach 1 but conceptually simulates correlated subquery
💡 This approach is often more efficient in SQL engines because EXISTS can short-circuit, but in code it looks similar to approach 1.
Interview Verdict: Accepted
This approach is preferred in SQL for correlated subqueries with EXISTS due to potential optimizations.