Relix

Problem solving

Has at least one

Grain: one row per entity · Class: Existence · Signals: any, at least one, has, ever, some, with a · Operators: ⋉

The problem

"Which customers have placed at least one order? Which have ever placed one over £100?"

How to recognise it

The question says any, at least one, has, ever, some, or with a …. It keeps an entity when a matching row exists on the other side, and the tell is that the answer is one row per entity — the same customer, once, no matter how many orders they placed. If a plain join would return the customer once per order, existence wants them once: that is a semi-join (⋉), not a join.

A semi-join is the join you reach for when you want to filter by existence rather than bring the other table's columns in.

The data

Customers := [
| customer |
|----------|
| Ann      |
| Bo       |
| Cy       |
| Dee      |
];

Orders := [
| order_id | customer | amount |
|----------|----------|--------|
| 1        | Ann      | 120    |
| 2        | Ann      | 40     |
| 3        | Bo       | 200    |
| 4        | Cy       | 30     |
];

Ann has two orders, Cy has one small one, Dee has none.

Recipe: keep the entity when a match exists (⋉)

A semi-join takes a condition and keeps each left row at most once — Ann does not appear twice for her two orders:

Query
query { Customers ⋉ Customers.customer = Orders.customer Orders };
Result
 customer
 ────────
 Ann
 Bo
 Cy
(3 rows)

At least one that also passes a test puts the test in the join condition. Which customers have ever ordered over £100?

Query
query { Customers ⋉ Customers.customer = Orders.customer ∧ Orders.amount > 100 Orders };
Result
 customer
 ────────
 Ann
 Bo
(2 rows)

The condition is exists an order that is both this customer's and over £100 — one qualifying order is enough to keep the customer.

Variations

Pitfalls

Check it