Main Point
A query defines which information reaches an analysis or AI system. Investigate what it keeps, omits, repeats and leaves unknown before interpreting its output.
Key Points
- State the question and row grain before selecting a population.
- Inner joins return matching combinations; left joins retain the left-side records, with NULL in unavailable right-side fields.
- A missing value needs interpretation. It can change both coverage and the denominator of a calculation.
- Reconcile identifiers, counts, repeated values and missing fields across transformations. A narrower evaluation population supports a narrower claim.
1. Start from the service’s question
The continuing case is a fictional company’s order-and-returns assistant. A service investigator needs to see every shipped order, including records whose customer relationship needs attention. Begin with the fields and condition required for that purpose. The familiar expression below means: return order identifiers and amounts from the orders source for rows whose recorded status equals shipped. SQL is Structured Query Language. [PG-SELECT]
```sql
SELECT order_id, amount
FROM orders
WHERE status = 'shipped';
```
The request relies on the recorded status. It cannot establish that the source captured shipment correctly. Also, these snippets teach selection and matching; they are not a production access-control or query-security design.
2. Follow the missing match
Use exactly these invented records. Each order identifier and each customer identifier is unique in its own source. All three orders are shipped.
- O101 refers to C7.
- O102 refers to C8.
- O103 refers to C9.
- The customer source contains C7 and C8; it contains no C9 entry.
Joining on customer_id with an inner join yields O101–C7 and O102–C8. O103 contributes no row because it has no matching customer entry. No source order is deleted.
```sql
SELECT o.order_id, o.customer_id, c.customer_name
FROM orders AS o
INNER JOIN customers AS c ON o.customer_id = c.customer_id;
```
A left join starting from orders returns all three orders. For O103, the customer-side name is NULL. The order-side customer_id still contains C9. That distinction helps locate the broken relationship rather than erasing evidence of it. [PG-JOIN]
```sql
SELECT o.order_id, o.customer_id, c.customer_name
FROM orders AS o
LEFT JOIN customers AS c ON o.customer_id = c.customer_id;
```
With the stated unique customer keys, these results have two and three rows respectively. In a general left join, several matching right-side records can produce several output combinations for one left-side record. “Retains each left record” therefore does not guarantee the original row count. [PG-TABLE]
For a question about matched customers, the inner result can be appropriate. For investigating all shipped orders, losing O103 conceals relevant work. Check the source extract and identifier assignment; the cause of the missing relationship remains unknown.
The PostgreSQL 18 tutorial provides a real documented demonstration using weather and city records, including an unmatched place. It verifies the database behavior described here; it provides no measured evidence about this invented company’s outcomes. Version 18 documentation was checked on 29 October 2026. [PG-JOIN]
3. Interpret NULL and the denominator
NULL can mark unavailable or unknown information. Testing for it uses `IS NULL`; ordinary equality with NULL does not behave like equality between known values. A missing customer name cannot establish that a person has no name. An unknown reason for a recorded return cannot establish that no return happened. [PG-NULL]
For a separate invented set of three return cases, all costs use the same currency and period: $10, $20 and unknown. The known-value calculation is:
($10 + $20) ÷ 2 = $15 per case with a known cost; coverage = 2 of 3 cases.
The complete three-case average is unknown. Replacing the missing value with zero gives ($10 + $20 + $0) ÷ 3 = $10 per case, imposing a value. A confirmed zero would support that calculation. PostgreSQL `AVG(cost)` averages non-null values; `COUNT(*)` and `COUNT(cost)` can reveal total records and records contributing a cost. [PG-AGG]
```sql
SELECT COUNT(*) AS cases,
COUNT(cost) AS known_costs,
AVG(cost) AS known_cost_average
FROM return_cases;
```
This calculation assumes one row per return case. A join that repeats cases would require the grain to be repaired first.
4. Reconcile a changing result
One $120 order matched to three order lines produces three combinations carrying that order total. Summing it at line grain produces $360. A join can therefore multiply representations while leaving the underlying transaction unchanged. [PG-TABLE]
Ask four questions after each transformation:
- Which source identifiers were included or excluded, and why?
- How often does each identifier now occur?
- Which fields became missing, and what do those states mean?
- Which denominator and units support the reported calculation?
Keep a record of these answers alongside the query definition. Evaluation on only matched cases can omit unresolved cases that the service must handle. Whether its measured score rises or falls depends on the excluded cases; no score is supplied in this lesson. Population coverage is a prerequisite for interpreting a score.
5. Practice and transfer
Use the separate worksheet before opening the answer key. Choose the result that serves the service question, identify a potential multiplication, and report both a known-value average and its coverage. The next lesson follows those results into operational and analytical systems.
6. A dated example
Missing cases also matter outside a model test. Public Health England reported on October 4, 2020 that a data-load issue had kept 15,841 positive cases out of the figures expected between September 25 and October 2. People had received their test results normally. The reporting population was incomplete even though the source events existed. The statement identifies a transfer issue, rather than a SQL join. It shows why reconciling source cases with the reported population matters before interpreting a result.
7. Bringing the investigation together
The service question requires every shipped order to remain inspectable, including O103 with its unresolved customer link. Choose the join for that purpose, reconcile repeated order amounts, and report the known-cost average alongside its coverage. These checks explain which source evidence reached the result and what still needs investigation.
Learning Checks
Attempt each answer before expanding the reasoning.
M13-L03-Q01
Why can a model appear to perform better after an inner join? Think about which cases reach the evaluation.
Show reasoning
Difficult or incomplete cases may have been removed when they failed to match. The evaluation may then describe the retained subset rather than the real operating population. Compare the included and excluded cases before interpreting a performance claim.
M13-L03-Q02
Three return cases have costs of ten dollars, twenty dollars, and an unknown amount. What does the fifteen-dollar average describe, and what would change if the unknown became a confirmed zero?
Show reasoning
Fifteen dollars describes the two cases with known costs. A confirmed zero would make all three costs known, giving a ten-dollar average across the three cases. Replacing an unknown with zero without evidence would impose that same calculation through an assumption.
Sources
- PG-SELECT: PostgreSQL Global Development Group. *PostgreSQL 18 Documentation*, §2.5, “Querying a Table.” https://www.postgresql.org/docs/18/tutorial-select.html. Checked 29 October 2026.
- PG-JOIN: Same organization/edition, §2.6, “Joins Between Tables.” https://www.postgresql.org/docs/18/tutorial-join.html. Checked 29 October 2026.
- PG-TABLE: Same organization/edition, §7.2, “Table Expressions,” qualified joins and WHERE. https://www.postgresql.org/docs/18/queries-table-expressions.html. Checked 29 October 2026.
- PG-NULL: Same organization/edition, §9.2, “Comparison Functions and Operators.” https://www.postgresql.org/docs/18/functions-comparison.html. Checked 29 October 2026.
- PG-AGG: Same organization/edition, §9.21, “Aggregate Functions,” AVG/COUNT entries. https://www.postgresql.org/docs/18/functions-aggregate.html. Checked 29 October 2026.
- Public Health England, “PHE statement on delayed reporting of COVID-19 cases”, published 2020-10-04; updated 2020-10-05; event/context: Expected reporting dates 2020-09-25 through 2020-10-02; case-recorded dates are a separate time field. https://www.gov.uk/government/news/phe-statement-on-delayed-reporting-of-covid-19-cases (retrieved 2026-10-29). Historical reporting incident; does not establish SQL join causation or infer model performance.