A pipeline joins a clickstream DataFrame of 12 million sessions to a customer DataFrame with an inner join on customer_id, and the marketing team reports that the daily session count in the resulting report is about 8 percent below the raw feed. Anonymous sessions carry a null customer_id and have no matching customer row. The report has to retain every session, with the customer attributes empty where no customer exists. Which change meets the requirement?
report = sessions.join(customers, on="customer_id", how="inner")- AKeep the inner join and add a second pass that unions the unmatched sessions back on, with the customer columns dropped from that side.
- BChange the join type to cross, so that every session is paired with the customer DataFrame and no session row is discarded by the join.
- CChange the join type to left, so that every session row is retained and the customer columns hold nulls wherever no match is found. Correct
- DReplace the null customer_id values with an empty string before the inner join, so that the anonymous sessions find a match on the customer side.
Why A is wrong: This does recover the missing sessions, so it looks workable, but dropping the customer columns leaves the two sides with different schemas, so the union is rejected and a single join type already gives the wanted result.
Why B is wrong: A cross join does keep every session, which is the surface appeal, but it pairs each session with every customer row, multiplying the report to an enormous size instead of preserving one row per session.
Why C is correct: A left join preserves every row of the left side regardless of whether the right side matches, filling the right side columns with nulls, which is precisely the outcome the report requires.
Why D is wrong: Substituting a sentinel value is a familiar tactic for null handling, but no customer row carries an empty customer_id either, so the inner join still discards those sessions and the count remains short.