Why might a LEFT JOIN behave like an INNER JOIN?
intermediateAnswer
Because a filter on the right-hand table was placed in WHERE instead of ON.
The join runs first, producing NULLs for unmatched left rows. WHERE then evaluates after, and right.status = 'shipped' is not true for NULL, so those rows are discarded — exactly the rows the LEFT JOIN existed to preserve.
Move the condition into the ON clause. The rule of thumb: conditions on the preserved table go in WHERE, conditions on the optional table go in ON.
Related