> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encodebox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Query patterns

> Common EventFrame and Cohort patterns with plain-English notes.

Patterns for **EventFrame** and **Cohort**. Decision guide: [Which API?](/which-api).

```python theme={null}
import encodebox as eb

eb.register_connector("connectors/postgres_local_sentinel/connector.yml")
db = eb.connect(..., connector="postgres_local_sentinel")
```

## Matching codes

Decide which code strings count as a hit.

| Form                   | Example              | Meaning                                    |
| ---------------------- | -------------------- | ------------------------------------------ |
| One code               | `"E11"`              | Prefix/exact/… on that code (`code_set=0`) |
| Several codes, one set | `["45378", "45380"]` | Any of these (OR)                          |
| Several sets           | `[["E11"], ["I10"]]` | UNION; `code_set` tells which set          |

```python theme={null}
# Colonoscopy CPT list — any code matches
db.procedure.matching(
    ["45378", "45380", "45385"],
    code_type="C4",
    match="exactly",
)

# Diabetes OR hypertension as separate sets
db.diagnosis.matching(
    [["E11"], ["I10"]],
    code_type="10",
    match=["starts_with", "exactly"],
)
```

Match aliases: `starts_with`, `exactly`, `contain`, `end with`.

## Confirmed condition (≥2 days)

"Seen at least twice on different calendar days."

```python theme={null}
confirmed = (
    db.diagnosis
    .matching("E11", code_type="10", match="starts_with")
    .occurring(at_least=2)
    .first_per_patient()
)
```

Same-day duplicates count once. For legacy row counting: `occurring(at_least=2, count_distinct_on=None)`.

## Gap-separated index

"Two visits far enough apart; index at the first of that pair."

```python theme={null}
index = (
    db.diagnosis
    .matching("E11", code_type="10", match="starts_with")
    .occurring(at_least=2, gap_days=30)
    .with_index_date()
    .first_per_patient()
)
```

## Position filter

"Only primary diagnosis rows."

```python theme={null}
db.diagnosis.matching("E11", code_type="10").in_position("primary")
```

## Cohort with coded washout

"Index patients, age and enrollment filters, drop cancer in the prior year."

```python theme={null}
cohort = (
    eb.Cohort("study", database=db)
    .entry(index, index="first")
    .include(db.demographic.age_at_index(18, 89))
    .include(db.enrollment.covering_index(days_before=365, days_after=0))
    .exclude(db.diagnosis.matching("C", match="starts_with"), window=(-365, 0))
)
print(cohort.attrition())
```

## Cohort with another EventFrame

Pass EventFrames to `.include` / `.exclude` (with optional `window=`) when the rule is itself an EventFrame.

```python theme={null}
other = (
    db.diagnosis
    .matching("E10", code_type="10", match="starts_with")
    .occurring(at_least=2, gap_days=30)
    .with_index_date()
    .first_per_patient()
)

cohort = (
    eb.Cohort("t2dm", database=db)
    .entry(index, index="first")
    .include(db.demographic.age_at_index(18, 89))
    .include(db.enrollment.covering_index(days_before=365, days_after=0))
    .include(other, window=(-365, 0))
    .exclude(db.diagnosis.matching("C", match="starts_with"), window=(-365, 0))
)
```

`window=(before, after)` is always days relative to the **cohort entry** index date. Omit `window` to require membership with no timing filter.

## Cross-domain event union

"Stack diagnosis and procedure hits into one stream."

```python theme={null}
dx = db.diagnosis.matching("E11", code_type="10")
px = db.procedure.matching("45378", code_type="C4", match="exactly")
combined = dx.union(px)
```

## Next

* [Which API?](/which-api)
* [Walkthrough](/walkthrough)
* [Migration](/migration)
