mirror of
https://github.com/lancedb/lancedb.git
synced 2026-10-30 23:36:52 +00:00
## Summary - Complete the SQL reference: `ATTACH DATABASE`, the `CHANGES` clause, and `dedupe()`/`duplicate_pairs()` (verified against current sophon source; these were recently renamed from `vector_dedup`/`vector_duplicate_pairs`). Fix the blob-column default-projection claim and add the previously undocumented `blob_descriptor()`. - Enrich the gated Functions draft (still `.mintignore`'d, pre-release): chained Functions over blob outputs, GPU-produced blobs, Secrets, multi-input/output binding, `code=[module]` packaging. - Upgrade the materialized-view and computed-column auto-refresh drafts with precise, verified catch-up semantics, and add the missing `ALTER MATERIALIZED VIEW` / `CREATE ... WITH(...)` sections (also gated — the automatic-refresh scheduler is still dev/staging-only). - Thread one running example (video frames → GPU extract/caption → dedup → auto-refreshing materialized view) through Functions, materialized views, and the LeRobotDataset integration guide instead of a separate tutorial. - Rename "LanceDB OSS"/"OSS" to "LanceDB Embedded"/"Embedded" throughout (52 files); activate the existing availability-comparison mechanism on `basics/offerings.mdx` for a full feature-by-feature comparison table.
79 lines
2.3 KiB
Plaintext
79 lines
2.3 KiB
Plaintext
---
|
|
title: "Subqueries"
|
|
sidebarTitle: "Subqueries"
|
|
description: "Queries inside queries: scalar, IN, EXISTS, correlated, and derived tables."
|
|
icon: code-branch
|
|
keywords: ["subquery", "exists", "in", "correlated", "derived table", "lateral"]
|
|
availability:
|
|
embedded: unavailable
|
|
enterprise: available
|
|
---
|
|
|
|
A subquery is allowed anywhere an expression or a relation is.
|
|
|
|
## As a relation {#derived}
|
|
|
|
```sql
|
|
SELECT * FROM (
|
|
SELECT category, count(*) AS n FROM documents GROUP BY category
|
|
) AS counts
|
|
WHERE n > 100
|
|
```
|
|
|
|
A derived table needs an alias. Its result cannot be
|
|
[sampled](/sql/dql/sampling); sample the table inside it instead:
|
|
|
|
```sql
|
|
SELECT * FROM (SELECT * FROM documents TABLESAMPLE (10)) d
|
|
```
|
|
|
|
## As a scalar {#scalar}
|
|
|
|
```sql
|
|
SELECT title, (SELECT count(*) FROM revisions r WHERE r.doc_id = d.id) AS revisions
|
|
FROM documents AS d
|
|
```
|
|
|
|
A scalar subquery returns one column and at most one row. No rows produces
|
|
`NULL`; more than one row is an error.
|
|
|
|
## IN and EXISTS {#in-exists}
|
|
|
|
```sql
|
|
SELECT title FROM documents
|
|
WHERE category_id IN (SELECT id FROM categories WHERE active)
|
|
|
|
SELECT title FROM documents AS d
|
|
WHERE EXISTS (SELECT 1 FROM revisions r WHERE r.doc_id = d.id)
|
|
```
|
|
|
|
Use `EXISTS` to test whether a matching row exists and `IN` to test membership
|
|
in a set of values. The optimizer may rewrite either into a join; inspect
|
|
`EXPLAIN` before choosing one for performance reasons.
|
|
|
|
`NOT IN` and `NOT EXISTS` differ on nulls: `NOT IN` against a set containing a
|
|
null yields no rows, because the comparison is unknown rather than false. Prefer
|
|
`NOT EXISTS` unless you have ruled nulls out.
|
|
|
|
## Correlated subqueries {#correlated}
|
|
|
|
A subquery referencing a column from the enclosing query, such as `d.id` above,
|
|
is correlated, and is conceptually evaluated per outer row. The planner usually
|
|
rewrites it into a join.
|
|
|
|
<Note>
|
|
Check with [`EXPLAIN`](/sql/dql/explain) when a correlated subquery is slow. A plan
|
|
showing a join has been optimized; one showing a repeated scan has not, and
|
|
rewriting it as an explicit [join](/sql/dql/join) is the fix.
|
|
</Note>
|
|
|
|
## CTEs as an alternative {#ctes}
|
|
|
|
A [CTE](/sql/dql/select#ctes) is a named subquery, and is usually more readable when
|
|
the same subquery appears twice or when nesting gets deep.
|
|
|
|
```sql
|
|
WITH active AS (SELECT id FROM categories WHERE active)
|
|
SELECT title FROM documents WHERE category_id IN (SELECT id FROM active)
|
|
```
|