# Filtering With WHERE: SQL and Vectors Together — Vector Databases

Source: https://www.geekswithgeeks.com/en/vector-databases/p-filter

> Combine similarity ranking with relational conditions.

## Ordinary SQL conditions just work

Because the vector is a column, you filter with ordinary `WHERE`: `WHERE tenant = 'acme' AND year = 2025 ORDER BY embedding <=> :q LIMIT 2`. You can also **join** to other tables (users, permissions, products), use `IN` lists, ranges, `OR` and **row-level security** to enforce who may see which rows, which is a major advantage over engines with limited query languages. Be aware that with an **approximate index** the order of operations matters (the next section shows a filter that returns zero rows), and an exact scan always honours the filter. Put **security filters in the query or in row-level security**, never in application text prompts.

## Similarity plus relational filters, run

I ran this SQL on PostgreSQL 16 with the pgvector extension, version 0.8.6, in a Docker container. Restricted to tenant `acme` and year 2025, the 2022 policy and the other tenant's memo are excluded, leaving the leave policy and the travel document, nearest first.

```sql
SELECT id, tenant, year, body
FROM docs
WHERE tenant = 'acme' AND year = 2025
ORDER BY embedding <=> '[1,0,0]'
LIMIT 2;
```

Output:

```
 id | tenant | year |       body        
----+--------+------+-------------------
  1 | acme   | 2025 | leave policy 2025
  3 | acme   | 2025 | travel and hotels
(2 rows)
```

## Index your filter columns too

A B-tree index on `tenant` or `year` helps the planner when a filter is selective. Verify with EXPLAIN.

**Quiz:** Which is a strength of pgvector for filtering?

- [x] Full SQL: joins, ranges, row-level security
- [ ] No filtering is possible
- [ ] Only equality on one field
- [ ] Filtering only in the prompt

*Answer:* Full SQL: joins, ranges, row-level security. The vector is just another column in a relational database.
