Watch 2 video solutions for Product's Price for Each Store, a easy level problem involving Database. This walkthrough by Frederik Müller has 2,730 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Table: Products
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| product_id | int |
| store | enum |
| price | int |
+-------------+---------+
In SQL, (product_id, store) is the primary key for this table.
store is a category of type ('store1', 'store2', 'store3') where each represents the store this product is available at.
price is the price of the product at this store.
Find the price of each product in each store.
Return the result table in any order.
The result format is in the following example.
Example 1:
Input: Products table: +-------------+--------+-------+ | product_id | store | price | +-------------+--------+-------+ | 0 | store1 | 95 | | 0 | store3 | 105 | | 0 | store2 | 100 | | 1 | store1 | 70 | | 1 | store3 | 80 | +-------------+--------+-------+ Output: +-------------+--------+--------+--------+ | product_id | store1 | store2 | store3 | +-------------+--------+--------+--------+ | 0 | 95 | 100 | 105 | | 1 | 70 | null | 80 | +-------------+--------+--------+--------+ Explanation: Product 0 price's are 95 for store1, 100 for store2 and, 105 for store3. Product 1 price's are 70 for store1, 80 for store3 and, it's not sold in store2.
Problem Overview: The table stores product prices in separate columns for each store (store1, store2, store3). The task is to convert this wide format into a normalized result where each row contains product_id, store, and price, excluding NULL prices.
Approach 1: UNION ALL Unpivot (O(n) time, O(1) space)
The straightforward solution is to simulate an unpivot operation using UNION ALL. Run three separate SELECT queries—one for each store column—and combine them with UNION ALL. Each query outputs the same schema: product_id, a constant store name, and the corresponding price column. Add a WHERE price IS NOT NULL filter in each query so rows with missing prices are excluded. Because each row from the table is scanned once per store column, the time complexity is O(n) relative to the number of products, and space complexity is O(1) aside from the result set. This approach is simple, readable, and widely supported across SQL engines.
Approach 2: CROSS JOIN with Conditional Selection (O(n) time, O(1) space)
Another method is to generate store labels using a small derived table and combine it with the products table using CROSS JOIN. The query then uses a CASE expression to map each store label (store1, store2, store3) to the correct column. After computing the value, filter out rows where the resulting price is NULL. This approach effectively converts columns into rows without repeating multiple SELECT blocks. Time complexity remains O(n) because each product is evaluated for a fixed number of stores, and space complexity stays O(1). It’s useful when the number of store columns is small and fixed.
Both solutions rely on standard database querying techniques and simple SQL transformations. The key idea is recognizing that the schema must be normalized by converting columns into rows. Using UNION ALL is the most explicit way to do this and is often easier to read during code reviews. The technique is conceptually similar to an UNION-based data transformation.
Recommended for interviews: The UNION ALL approach. Interviewers expect a clear unpivot strategy using multiple selects. It shows you understand how to reshape relational data and handle NULL filtering cleanly. The CROSS JOIN method demonstrates deeper SQL flexibility but is less common for quick interview solutions.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| UNION ALL Unpivot | O(n) | O(1) | Best general solution. Clear, readable, and supported in all SQL engines. |
| CROSS JOIN + CASE Mapping | O(n) | O(1) | Useful when dynamically mapping column labels to rows without repeating multiple SELECT queries. |