cswork / libraryOpen practice workspace

Coding questions · Fannie Mae

Assess SQL joins, unions, windows, dedup, and pandas

This question evaluates proficiency in SQL and pandas data-manipulation techniques, including aggregations with NULL semantics, various join types, set operations and deduplication, window functions, and reconciling normalized and denormalized sources.

Using the schema and sample data below, answer all sub-questions. Unless stated, assume ANSI SQL and explain any dialect-specific choices.

Schema:

  • customers(customer_id PK, name)
  • orders(order_id PK, customer_id FK->customers, order_date DATE, amount DECIMAL(10,2))
  • order_items(item_id PK, order_id FK->orders, product_id FK->products, qty INT, price DECIMAL(10,2))
  • products(product_id PK, name, category)
  • web_orders(order_id, customer_id, amount)
  • store_orders(order_id, customer_id, amount)
  • employees(emp_id PK, name, salary INT)

Sample tables (tiny): customers

customer_idname
1Alice
2Bob
3Carol

orders

order_idcustomer_idorder_dateamount
10112025-08-28120.00
10212025-08-3080.00
10322025-08-2950.00
10532025-08-30NULL

order_items

item_idorder_idproduct_idqtyprice
1101101120.00
210211240.00
310312150.00

products

product_idnamecategory
10PhoneElectronics
11CableElectronics
12BookMedia

web_orders

order_idcustomer_idamount
201150.00
202150.00
202150.00

store_orders

order_idcustomer_idamount
301150.00
202150.00
302250.00

employees

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Tasks:

  1. Aggregations and NULLs: Write queries that compute per-customer: (a) COUNT(), COUNT(amount), SUM(amount), AVG(amount), MIN/MAX(order_date). Show the result difference caused by orders.amount being NULL for customer_id=3. Explain COUNT(column) vs COUNT(), and how AVG ignores NULLs. Also compute total revenue from order_items using SUM(qty*price) and reconcile it to SUM(orders.amount); explain any mismatch and how to detect inconsistencies.
  2. Joins: (a) INNER JOIN customers↔orders to list customers who placed orders. (b) LEFT JOIN customers↔orders to include customers with zero orders; return 0 as totals for those. (c) FULL OUTER JOIN customers↔orders and explain which rows appear only on one side. (d) CROSS JOIN products↔(SELECT DISTINCT category) to illustrate Cartesian output and how to limit it. Provide queries and one or two expected result rows to prove understanding.
  3. UNION vs UNION ALL: Combine web_orders and store_orders into a single set of (order_id, customer_id, amount). (a) Using UNION ALL, count total rows and the number of duplicate order_ids. (b) Using UNION (distinct), show deduplicated rows. (c) Return only the order_ids that appear in both sources without using INTERSECT.
  4. Window functions: (a) For each customer, rank their orders by amount DESC and return the top 1 per customer using ROW_NUMBER. (b) Compute a running total of amount per customer ordered by order_date; show partition boundaries. (c) For August 2025, compute each customer’s rank by monthly spend using SUM(amount) OVER(PARTITION BY customer_id) and then DENSE_RANK across customers. Explain why a window does not collapse rows like GROUP BY.
  5. View vs table: Create a view top_spenders_2025_08(customer_id, total_amount) over orders. Is it updatable? Under what conditions? What happens if the base table adds a NOT NULL column or if the view definition references a column later dropped? Discuss pros/cons of views vs materialized tables for this case and how to refresh a materialized view (name your chosen RDBMS).
  6. Hide duplicated rows (select-time): Return one row per distinct (order_id, customer_id, amount) from web_orders without deleting data. Show two approaches: DISTINCT and ROW_NUMBER() filtering; discuss performance and which preserves deterministic choice.
  7. Remove duplicated rows (data-change): In web_orders, delete true duplicates keeping the lowest ROW_NUMBER by (order_id, customer_id, amount) and explain how you’d do this safely in a transaction with a reproducible tie-breaker. Provide the DELETE…CTE you would run.
  8. LC #177 (Nth highest salary): Using employees(name, salary), write a query that returns the Nth highest distinct salary given a parameter :n. Show outputs for n=1,2,3 on the sample data and explain behavior when n exceeds the number of distinct salaries.
  9. Improve SQL efficiency: Propose an indexing strategy for the above workloads (consider orders(customer_id, order_date), order_items(order_id), and covering indexes). Show how to rewrite one query to be sargable (e.g., avoid functions on indexed columns), and explain when EXISTS outperforms IN and when a window function can replace a self-join. Describe how you’d verify improvements using an execution plan and timing.
  10. Python pandas merge vs join vs concat: Given DataFrames below, specify the exact pandas calls (with how=, on=, axis=, ignore_index=, validate=) to: (a) left-join spend onto cities; (b) inner-join both then right-join to keep ids only in df_b; (c) stack df_a and a new rows frame vertically; (d) align on index instead of column; (e) explain when concat vs merge is appropriate.

DataFrames: df_a

idcity
1SF
2NYC
3LA

df_b

idspend
280
320
410

df_c

idtag
3vip

Customer aggregates, NULL handling, and revenue reconciliation

Using the tables below, return one combined result set for two checks:

  1. result_set = 'customer_aggregates': one row per customer with COUNT(*), COUNT(amount), SUM(amount), AVG(amount), MIN(order_date), and MAX(order_date) over orders. This should show how the NULL amount for customer_id = 3 affects SUM/AVG/COUNT(amount).
  2. result_set = 'revenue_reconciliation': one summary row comparing SUM(orders.amount) to SUM(order_items.qty * order_items.price), with their difference. Compute the order amount total separately from the item total so orders are not double-counted by the order_items join.

Use columns result_set, customer_id, name, order_count_all, order_count_non_null_amount, total_amount, avg_amount, first_order_date, last_order_date, sum_orders_amount, sum_items_value, and difference. Fields that do not apply to a row should be NULL.

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

One combined result set: per-customer order aggregates followed by a revenue reconciliation row. The reconciliation computes SUM(orders.amount) separately from SUM(order_items.qty * order_items.price) to avoid double-counting order amounts across item rows.

avg_amountcustomer_iddifferencefirst_order_datelast_order_datenameorder_count_allorder_count_non_null_amountresult_setsum_items_valuesum_orders_amounttotal_amount
1001NULL2025-08-282025-08-30Alice22customer_aggregatesNULLNULL200
602NULL2025-08-292025-08-29Bob11customer_aggregatesNULLNULL60
NULL3NULL2025-08-302025-08-30Carol10customer_aggregatesNULLNULLNULL
NULLNULL10NULLNULLNULLNULLNULLrevenue_reconciliation250260NULL

Hints

  1. Use COUNT(column) to show how NULL values are excluded from that count.
  2. Compute order-level and item-level revenue totals in separate CTEs before comparing them.
  3. Use typed NULLs when combining detail rows and summary rows with UNION ALL.

Inner, outer, and cross joins between customers, orders, and products

Using the same schema, write the INNER JOIN between customers and orders that lists customers who placed orders, returning customer_id, name, order_id, order_date, and amount. For the executable sample output, return the first two rows ordered by customer_id and order_id.

In your explanation, also describe how the result would differ for a LEFT JOIN from customers to orders, a FULL OUTER JOIN between customers and orders, and a CROSS JOIN between products and the distinct product categories.

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

The INNER JOIN query returns one row per order with the customer attached; all customers currently have at least one order, so all 4 orders appear. Below are two example rows from the INNER JOIN result.

amountcustomer_idnameorder_dateorder_id
1201Alice2025-08-28101
801Alice2025-08-30102

Hints

  1. Join customers.customer_id to orders.customer_id.
  2. Use an INNER JOIN when only matching customer/order pairs should appear.
  3. Order deterministically before limiting the sample rows.

UNION ALL vs UNION and finding overlapping order_ids

Using web_orders and store_orders, return the distinct combined set of (order_id, customer_id, amount) across both tables. Use UNION, not UNION ALL, so duplicate rows are removed, and order the output by order_id, customer_id, and amount.

In your explanation, also describe how you would use UNION ALL to count total combined rows and how to find order_ids that appear in both sources without using INTERSECT.

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

The UNION (distinct) query returns one row per unique (order_id, customer_id, amount) across web_orders and store_orders. With the sample data, there are four distinct rows.

amountcustomer_idorder_id
501201
501202
501301
502302

Hints

  1. UNION removes duplicate rows; UNION ALL preserves them.
  2. The duplicate row in the sample is order_id 202 for customer_id 1.
  3. Use an inner join between the two source tables to find overlapping order_ids without INTERSECT.

Window functions: ranking, running totals, and spend ranking

Using the orders table, write a PostgreSQL window-function query that returns the single highest-amount non-NULL order for each customer. Rank orders per customer by amount DESC; if a tie occurs, use the smaller order_id first. Return exactly order_id, customer_id, and amount, ordered by customer_id.

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

For part (a), the top-order-per-customer query returns one row per customer with the highest non-NULL order amount. With the sample data, customer 1's top order is 120.00 (order_id=101) and customer 2's top order is 60.00 (order_id=103); customer 3 is ignored because their only order has NULL amount.

amountcustomer_idorder_id
1201101
602103

Hints

  1. Use ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY amount DESC, order_id ASC).
  2. Filter the ranked CTE to rn = 1.

Creating a view of top spenders for August 2025

Define a view top_spenders_2025_08(customer_id, total_amount) over the orders table that summarizes each customer’s total non-NULL amount for orders in August 2025 (order_date between '2025-08-01' and '2025-08-31'). Then select from this view to see the results ordered by total_amount DESC. Discuss in words whether this view is updatable, how schema changes to the base table (e.g., adding a NOT NULL column or dropping a referenced column) might affect it, and pros/cons of using a plain view versus a materialized view for reporting.

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

The SELECT from top_spenders_2025_08 returns one row per customer who has non-NULL order amounts in August 2025, with their total spend. With the sample data, Alice has 200.00 and Bob has 60.00; Carol's NULL order is ignored.

customer_idtotal_amount
1200
260

Hints

  1. Define the view using a GROUP BY over customer_id with a WHERE filter restricting order_date to August 2025 and excluding NULL amounts.
  2. Aggregating views (with GROUP BY) are generally not updatable in most RDBMSs; think about how that affects INSERT/UPDATE operations through the view.

Hiding duplicate rows from web_orders at query time

Without modifying the data in web_orders, write two queries that return one row per distinct (order_id, customer_id, amount) from web_orders: (a) using SELECT DISTINCT, and (b) using ROW_NUMBER() OVER(PARTITION BY order_id, customer_id, amount ORDER BY web_order_id) and filtering to the first occurrence. Discuss which approach is more efficient and how using ROW_NUMBER gives deterministic control over which physical row you keep when there are duplicates.

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

Both approaches should return the same deduplicated set of (order_id, customer_id, amount) from web_orders. With the sample data there are two distinct logical orders: order_id 201 and 202.

amountcustomer_idorder_id
501201
501202

Hints

  1. SELECT DISTINCT is the simplest way to hide duplicates when you only care about the distinct combinations of columns.
  2. ROW_NUMBER() OVER(PARTITION BY ...) with ORDER BY web_order_id lets you deterministically keep, for example, the earliest inserted row.

Deleting true duplicate rows from web_orders safely

Assume web_orders has a surrogate primary key web_order_id. Using the sample data (which contains duplicate logical rows for order_id=202), write a DELETE statement that removes true duplicates and keeps the row with the lowest web_order_id for each distinct (order_id, customer_id, amount). Use a CTE with ROW_NUMBER() OVER(PARTITION BY order_id, customer_id, amount ORDER BY web_order_id) and delete rows where rn > 1. Then SELECT from web_orders to show the remaining rows. Your DELETE should be safe and deterministic.

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

After deleting true duplicates and keeping the row with the smallest web_order_id per (order_id, customer_id, amount), web_orders should contain only two rows: one for order_id 201 and one for a single copy of order_id 202.

amountcustomer_idorder_idweb_order_id
5012011
5012022

Hints

  1. Use a CTE to assign ROW_NUMBER within each duplicate group and then delete where rn > 1.
  2. Always order ROW_NUMBER() by a stable surrogate key (like web_order_id) so that the surviving row is deterministic.

Nth highest distinct salary using window functions

Using the employees(emp_id, name, salary) table, write a query that can be used to retrieve the Nth highest DISTINCT salary. Implement it by assigning a dense rank over salaries ordered descending and exposing both the rank and the salary. Show the ranks and salaries for the sample data, and explain how you would filter for a specific N (e.g., N=1,2,3). Also describe what happens when N exceeds the number of distinct salaries (no row is returned).

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

The query should return each distinct salary with its dense rank when ordered from highest to lowest. With the sample data, the 1st highest salary is 300, 2nd is 200, and 3rd is 100.

nsalary
1300
2200
3100

Hints

  1. First derive distinct salaries, then apply DENSE_RANK() OVER(ORDER BY salary DESC) to get the rank of each one.
  2. To get the Nth highest salary, wrap this query and filter WHERE n = :n (or a literal value like 2).

Indexing strategy and sargable predicates

Propose an indexing strategy for the workloads above, focusing on orders(customer_id, order_date) and order_items(order_id). Then, show how to rewrite a non-sargable filter into a sargable one, for example changing a function on an indexed date column into a range predicate so the index can be used. Also briefly explain when EXISTS can outperform IN and when a window function can replace a self-join. Implement your indexing proposal with CREATE INDEX statements and include one example sargable SELECT query that benefits from the indexes.

Table customers

columntypeconstraints
customer_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL

Sample data:

customer_idname
1Alice
2Bob
3Carol

Table orders

columntypeconstraints
order_idINTPRIMARY KEY
customer_idINTNOT NULL, FOREIGN KEY REFERENCES customers(customer_id)
order_dateDATENOT NULL
amountDECIMAL(10,2)

Sample data:

amountcustomer_idorder_dateorder_id
12012025-08-28101
8012025-08-30102
6022025-08-29103
NULL32025-08-30105

Table order_items

columntypeconstraints
item_idINTPRIMARY KEY
order_idINTNOT NULL, FOREIGN KEY REFERENCES orders(order_id)
product_idINTNOT NULL
qtyINTNOT NULL
priceDECIMAL(10,2)NOT NULL

Sample data:

item_idorder_idpriceproduct_idqty
1101120101
210240112
310350121

Table products

columntypeconstraints
product_idINTPRIMARY KEY
nameVARCHAR(100)NOT NULL
categoryVARCHAR(50)NOT NULL

Sample data:

categorynameproduct_id
ElectronicsPhone10
ElectronicsCable11
MediaBook12

Table web_orders

columntypeconstraints
web_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idweb_order_id
5012011
5012022
5012023

Table store_orders

columntypeconstraints
store_order_idINTPRIMARY KEY
order_idINTNOT NULL
customer_idINTNOT NULL
amountDECIMAL(10,2)NOT NULL

Sample data:

amountcustomer_idorder_idstore_order_id
5013011
5012022
5023023

Table employees

columntypeconstraints
emp_idINTPRIMARY KEY
nameVARCHAR(50)NOT NULL
salaryINTNOT NULL

Sample data:

emp_idnamesalary
1Alice100
2Bob200
3Carol300
4Dave300

Expected output

After creating the suggested indexes, the sargable SELECT query returns all orders on 2025-08-30. With the sample data, there are two such orders (order_ids 102 and 105).

amountcustomer_idorder_dateorder_id
8012025-08-30102
NULL32025-08-30105

Hints

  1. Composite indexes like (customer_id, order_date) help both lookups by customer and range scans on dates when combined appropriately in predicates.
  2. To make a predicate sargable, avoid wrapping indexed columns in functions; instead, rewrite to a range on the raw column (e.g., order_date between start and end).

pandas merge vs join vs concat for combining DataFrames

You have three pandas DataFrames df_a(id, city), df_b(id, spend), and df_c(id, tag) with the sample data below. Write the exact pandas calls (including how=, on=, axis=, ignore_index=, validate= where relevant) to: (a) left-join spend from df_b onto city rows in df_a; (b) inner-join df_a and df_b, and also produce a right join that keeps all ids from df_b; (c) vertically stack df_a and a new_rows DataFrame with the same columns; (d) perform a join aligned on the index instead of on an explicit column; (e) briefly explain (in comments or a string) when concat is appropriate versus merge/join. Return one row per sub-task with the corresponding pandas code snippet.

Table df_a

columntypeconstraints
idINTPRIMARY KEY
cityVARCHAR(10)NOT NULL

Sample data:

cityid
SF1
NYC2
LA3

Table df_b

columntypeconstraints
idINTPRIMARY KEY
spendINTNOT NULL

Sample data:

idspend
280
320
410

Table df_c

columntypeconstraints
idINTPRIMARY KEY
tagVARCHAR(10)NOT NULL

Sample data:

idtag
3vip

Expected output

The query returns one row per pandas task (a–e), with a task label and a string containing the appropriate pandas code snippet to perform the requested merge/join/concat operation.

pandas_codetask
df_a.merge(df_b, how='left', on='id', validate='one_to_one')a
inner_join = df_a.merge(df_b, how='inner', on='id', validate='one_to_one'); right_join = df_a.merge(df_b, how='right', on='id', validate='one_to_one')b
result = pd.concat([df_a, new_rows], axis=0, ignore_index=True)c
df_a.set_index('id').join(df_c.set_index('id'), how='left', validate='one_to_one')d
Use merge/join to combine columns based on key relationships; use concat to stack or align entire DataFrames along rows or columns when their schemas are compatible.e

Hints

  1. Use merge for key-based joins and concat for stacking aligned frames.
  2. The validate argument documents the expected one-to-one relationship.
  3. When returning code snippets from SQL, keep table-like identifiers inside string literals from being rewritten by the SQL engine.