One Document Type, a Million Files: Structured Extraction into the SQL Table RAG Queries

Much of the current RAG work focuses on letting a model discover the structure of a document collection: read every file, extract entities, infer relations, and a graph emerges that nobody had to design. But when you have five thousand copies of the same contract, there is nothing left to discover.

Ask the person who files those contracts what they look things up by. The answer takes about ten seconds: client, effective date, product, premium, renewal date, policy number.

Nobody found those six by reading the documents. They were designed years ago by whoever drew up the form, and every file since has been filled in against them. These files are the output of one repeatable process, and the process defines the fields.

So the collection is a database nobody typed. Its schema lives in the head of the person who handles the files, and the work is to get it out and write it into a table.

This article assumes the diagnostic from Article 14A (three kinds of corpus, and what building for the wrong one costs) already identified this shape: one document type, many copies. It covers what to do next:

  • The interview that produces the columns, question by question.
  • The two signals that tell a real column from a field that will break a filter later.
  • The index as a table of contents for the collection, and why it keeps growing.
  • What gets paid once per document, and what gets paid on every question.
  • The arithmetic, at fifty questions a day, that says when the preparation pays for itself.

This article is part of Part IV of Enterprise Document Intelligence, a series that builds an enterprise RAG system from four bricks. In Part IV, the input stops being a file and becomes a folder, and this is the folder shape where a table is the right answer.

🧭 New to the series? Start with the map: Prompt, Context, Loop sets out the three engineering layers every RAG system is built on—the prompt (the call itself), the context (what fills the model's window), and the loop (when the next call fires and when it stops)—and walks through the series article by article. It's the shortest way to see what's covered and where this one fits.

Diagram showing where this article sits in Part IV
Where this article sits: Part IV, the folder that becomes a table – Image by author

📓 Run the column test on your own folder in the companion notebook: declare the six columns, fill them across a folder of look-alike PDFs, then print the fill rate per column and watch two fields that sounded like columns come back half empty. Repo → doc-intel/notebooks-vol1.

Screenshot of the public companion-code repository
The public companion-code repo at doc-intel/notebooks-vol1 – Image by author

The worked example is an insurance portfolio, and it is fictional: the clients, policy numbers, and amounts were authored for the series and match no real insured or insurer. Section 3.2 gives a public folder you can run the same test on.

1. One Document Type, and the Columns That Came With It

Two things to settle before the interview: what makes this shape recognizable, and where its columns come from.

1.1. What the Shape Looks Like on a Shelf

On a physical shelf, this shape is a row of identical binders. Each binder has the same tabs, the same forms behind each tab, and the same blanks to fill in. The structure is uniform because the process that produced it was uniform. In software terms, the collection is a set of records in a fixed format—a table waiting to be materialized.

The columns are not discovered; they are inherited from the form design. The person who filed these documents knows the columns by heart because they've seen them a thousand times. The RAG system doesn't need to infer them; it needs to extract them consistently.

1.2. Where the Columns Come From

The columns come from the process, not the content. Whoever designed the form defined the fields, and every file since has been filled against those definitions. The schema is external to the documents themselves—it lives in the process documentation, the form templates, and the mental model of the people who work with them.

In the insurance example, the columns are: client, effective date, product, premium, renewal date, policy number. These six fields are the answer to "what do you look things up by?"—they are the keys under which the collection is structured, and they are the natural columns for the SQL table.

2. The Interview: Producing the Columns, Question by Question

Before writing any extraction code, interview the person who knows the collection. The goal is to elicit the columns in a structured way, not to guess them from a sample of documents. The interview should cover:

  • What do you look up? Start with the questions people ask of the collection. What are the common lookups? For the insurance files, it's client and policy number.
  • What filters do you use? When you narrow down results, what criteria do you apply? Effective date and renewal date are common filters for time-based queries.
  • What values are always present? Some fields are always filled in every document; others are sometimes blank. The always-present fields are safer column candidates.
  • What would you never filter by? Fields that are free-text notes or rarely used for lookup might be better excluded from the table.

Each question should be concrete, tied to a real lookup scenario. The goal is to walk away with a candidate column list, each with a description and an example value.

3. Two Signals That Distinguish a Real Column from a Field That Will Break a Filter

Not every field that seems important will work as a column. A column must support filtering and aggregation reliably. There are two signals that separate a real column from a field that will cause problems:

3.1. Signal 1: Fill Rate

A real column is present in the vast majority of documents. If a field is missing in more than 10–20% of files, filtering by it will silently exclude relevant documents. For example, if "renewal date" is only filled in for 60% of policies, a query "renewal date after 2026-01-01" will miss 40% of the portfolio.

Test: run a fill rate analysis across a sample folder. For each candidate column, count how many documents have a non-empty value. Columns with high fill rate (≈100%) are viable; low fill rate fields might still be useful as optional tags, but not as primary columns.

3.2. Signal 2: Value Consistency

A real column has a consistent format, type, and vocabulary across the collection. If "effective date" appears as "2026-08-01" in one file and "Aug 1, 2026" in another, filtering becomes messy. Similarly, if "product" has 50 variations of the same product name (e.g., "Annuity", "annuity plan", "ANNUITY"), the column will break aggregation.

Test: check the distinct values and their normalization. If you need to normalize heavily (date parsing, case folding, synonym mapping), the column is still useful but requires an extraction step that produces a clean, canonical form.

If a field fails either signal, it can still be used as a secondary index, but it shouldn't be a primary column in the SQL table.

4. The Index: A Table of Contents for the Collection

The SQL table acts as a table of contents for the folder. Each row is a document, and each column is a field that points to content. This index is not static—it grows as new documents arrive. Every new file is extracted and added as a new row. The index also supports the RAG loop: instead of reading every document to answer a query, the system first filters the table to a small set of candidate rows, then retrieves only those documents for synthesis.

The index grows because the collection grows. In an enterprise, the folder is live—contracts are renewed, new policies are issued, files are updated. The extraction pipeline must run incrementally, processing only new or changed files and updating the table accordingly.

5. Cost Model: What Gets Paid Once vs. Every Question

Building the table has two cost components:

  • One-time per document: The extraction cost for each file—calling an LLM or a rules-based parser to fill the columns. This is amortized over the lifetime of the document.
  • Recurring per question: The cost of querying the table and retrieving relevant documents. This is much lower than reading the entire collection for each query.

In a naive RAG system, every question reads (or embeds) every document—that's a per-question cost proportional to the collection size. With the table, the per-question cost is proportional to the result set size, which is often small (e.g., 10–100 documents out of a million).

6. The Arithmetic: When Does Preparation Pay Off?

Suppose you have 10,000 documents. Extraction costs $0.10 per document (e.g., using an LLM with moderate token usage), so the one-time cost is $1,000.

Assume a naive RAG system costs $1.00 per question (embedding all documents or reading a large context). With the table, each query costs $0.20 (SQL filter + retrieval of a handful of documents).

At 50 questions per day:

  • Naive: 50 × $1.00 = $50/day.
  • Table-based: 50 × $0.20 = $10/day.
  • Savings: $40/day.

The $1,000 extraction cost pays for itself in 25 days (1,000 / 40). After that, the table-based system saves $40 every day. Over a year (250 working days), that's $10,000 in savings.

The arithmetic scales: the larger the collection and the higher the query volume, the faster the investment returns. For a million files, the per-question savings are even more dramatic because the naive cost grows with collection size, while the table-based cost remains roughly constant.

Additionally, the table enables new capabilities: SQL joins with other business data, aggregations for reporting, and consistent filtering—none of which are practical with naive RAG.

7. Conclusion

When you have one document type and many copies, the structure is already there—it just needs to be extracted into a table. The process is: interview to find the columns, test for fill rate and consistency, build the extraction pipeline, and maintain the index as the collection grows. The cost model shows that this preparation pays for itself quickly at scale, and the resulting SQL table makes RAG queries fast, accurate, and auditable.

In the next article in Part IV, we'll look at the folder shape where a table isn't the right answer—the heterogeneous corpus—and how to handle that case.

via Towards Data Science

Related