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

# Partial Filters

> Keep parts of your query unaffected by dashboard filters — just add a `$`.

## What are Partial Filters?

When someone filters a dashboard, those filters normally apply to every table in your widget's query. But sometimes you don't want that. Maybe you're comparing this month's sales to all-time sales, and you need that all-time number to stay put no matter what filters get applied.

Partial Filters solve this. Add a `$` to any table reference, and that reference gets left alone. Everything else filters like normal.

## The basics

Just put a `$` on the table name you want to protect from filters:

```sql theme={null}
SELECT COUNT(*) FROM $ORDERS
```

That's it. The `$` is a signal to the filtering layer — it gets stripped out before your query actually runs, so your database never sees it.

You can put the `$` wherever it's convenient:

| You write | What happens             |
| --------- | ------------------------ |
| `ORDERS`  | Filtered (the default)   |
| `$ORDERS` | Not filtered             |
| `ORDERS$` | Not filtered             |
| `ORD$ERS` | Not filtered (but, why?) |

## Where to add the `$`

Two places:

1. **Query Builder** when you're writing or editing the SQL
2. **Dashboard Edit** when you're tweaking a widget in place

Changes apply the next time the widget runs.

## Examples

### "What % of all-time orders happened this period?"

You want the numerator to follow the dashboard's date filter, but the denominator should always be the all-time total.

```sql theme={null}
WITH current_period AS (
  SELECT COUNT(*) AS orders_in_period
  FROM ORDERS              -- filtered: reflects the selected period
),
all_time AS (
  SELECT COUNT(*) AS total_orders
  FROM $ORDERS             -- not filtered: always all-time
)
SELECT
  ROUND(
    (SELECT orders_in_period FROM current_period) * 100.0 /
    NULLIF((SELECT total_orders FROM all_time), 0),
    2
  ) AS percentage_of_total;
```

### "Show filtered revenue next to a company-wide benchmark"

```sql theme={null}
SELECT
  (SELECT SUM(amount) FROM SALES)  AS filtered_revenue,   -- moves with filters
  (SELECT AVG(amount) FROM SALES$) AS company_average;    -- stays constant
```

### Mixing filtered and unfiltered references in one query

```sql theme={null}
SELECT
  u.region,
  COUNT(o.id)      AS filtered_orders,
  ref.total_users
FROM ORDERS o                       -- filtered
JOIN USERS u ON u.id = o.user_id    -- filtered
LEFT JOIN (
  SELECT region, COUNT(*) AS total_users
  FROM $USERS                       -- not filtered: full population per region
  GROUP BY region
) ref ON ref.region = u.region
GROUP BY u.region, ref.total_users;
```

The same table (`USERS`) appears twice and behaves differently in each spot — that's the whole point of putting the `$` on individual *references* rather than the table itself.

## Tips

**Use it sparingly.** The default — filtering everything — is almost always what you want. Only reach for `$` when you have a specific reason to keep a reference static.

**It's per-reference, not per-table.** If `ORDERS` shows up three times and you want two of them unfiltered, mark those two and leave the third alone.

**Leave a comment.** Future you (or a teammate) will appreciate a quick note like `-- baseline, intentionally unfiltered` next to any `$`-marked reference.

**Schema-qualified names work too.** Just put the `$` next to the table part: `analytics.$ORDERS` or `analytics.ORDERS$`.

## FAQ

**Does this work for tables, charts, and KPIs?**
Yes — same behavior across all widget types.

**What if I forget the `$`?**
Nothing breaks. The reference just gets filtered like any other, and your results will move with the dashboard filters.

**Will the `$` show up in query errors or results?**
No. It's stripped before the query reaches the database, so your column names, joins, and aliases all work exactly as written.
