cswork / libraryOpen practice workspace

Coding questions · Citadel

Implement left join on Python lists, no packages

This question evaluates a candidate's ability to implement SQL-style left join semantics using pure Python lists and dictionaries, testing skills in hashing, handling duplicate and missing keys, and reasoning about algorithmic time and space complexity.

Implement a left join in pure Python (no external packages, no pandas). Input: left = list of dicts with key 'id' and arbitrary other fields; right = list of dicts with key 'id' and fields to append (disjoint names from left). Requirements: (1) Preserve the original order of 'left' and left duplicates. (2) Support one-to-many matches on 'right' (i.e., duplicate 'id's): emit one output row per matching right row; if no match, emit a single row with right fields set to None. (3) Time O(n + m) and extra space O(n + m) by using hashing; explain how you would reduce memory when m is huge (e.g., streaming or external sort). (4) Handle missing 'id' keys robustly. Provide clear function signatures and tests on small examples.

Left Join With One-to-Many Matches, Preserving Left Order and Duplicates

You are given two tables that represent two lists of records:

  • left_records: the primary list. It contains an id (which may be NULL) and other fields.
  • right_records: the lookup list. It also contains an id (which may be NULL) and fields to append to the left.

Write a SQL query that performs a LEFT JOIN of left_records to right_records on id with the following requirements:

  1. Preserve the original order of rows from left_records using left_seq (and preserve duplicates in left_records).
  2. Support one-to-many matches on right_records (i.e., multiple rows in right_records can share the same id). For each left_records row, return one output row per matching right_records row.
  3. If a left_records row has no matching right_records row (including when left_records.id is NULL), return exactly one output row with the right-side columns as NULL.
  4. Handle missing IDs robustly: rows where left_records.id is NULL should not match anything (even if right_records.id is NULL).

Return these columns: left_seq, id, left_name, right_attr.

Order the final output by left_seq, and for rows with multiple matches, order by right_seq.

Table left_records

columntypeconstraints
left_seqINTPRIMARY KEY, NOT NULL
idINT
left_nameVARCHAR(50)NOT NULL

Sample data:

idleft_nameleft_seq
1Alpha1
2Beta2
2Beta (duplicate left row)3
3Gamma4
NULLNo ID Row5
4Delta6

Table right_records

columntypeconstraints
right_seqINTPRIMARY KEY, NOT NULL
idINT
right_attrVARCHAR(50)NOT NULL

Sample data:

idright_attrright_seq
2B110
2B211
4D112
5E1 (unused)13
NULLNULL-ID right row (should not match)14

Expected output

One row per left record per matching right record. If no match (including left.id IS NULL), right_attr is NULL. Output is ordered by left_seq, then right_seq for deterministic ordering of one-to-many matches.

idleft_nameleft_seqright_attr
1Alpha1NULL
2Beta2B1
2Beta2B2
2Beta (duplicate left row)3B1
2Beta (duplicate left row)3B2
3Gamma4NULL
NULLNo ID Row5NULL
4Delta6D1

Hints

  1. A LEFT JOIN will keep all rows from the left table and produce NULLs on the right when there is no match.
  2. If the right table has duplicate IDs, a normal join naturally returns one output row per matching right row.
  3. To preserve the original left order in SQL, include an explicit sequencing column (here, left_seq) and ORDER BY it.