Scope & vantage. Assessed mid-2026. Target use case: the interface an analytics team expresses its logic in — transformations, metric definitions, and the ad-hoc questions that become permanent. Axes are interface-specific, not comparable with the platform assessments, and Approachability is inverted so higher always means better. "DataFrame APIs" covers pandas, Polars and Spark DataFrames as a family; the differences between them are a separate piece.
1. Executive summary
SQL wins, it is not close, and the interesting part is why the LLM era made that more true rather than less. It scores 4.9 on Durability and 4.9 on Tooling — the two highest numbers in this assessment — and leads on verifiability, portability and governance.
The prediction in 2023 was that natural language would replace SQL. What actually happened is that LLMs generate SQL better than they generate anything else, because fifty years of it exists in the training data and it is a small, declarative, verifiable language. So the LLM did not remove the need for SQL — it removed a chunk of the need to type SQL, while leaving the need to read, review and trust it exactly where it was. That is a productivity shift, not a replacement, and the difference matters enormously for how you build.
Which is why text-to-SQL scores 2.6 on correctness, the lowest number on this page. A natural-language question is ambiguous by nature; a query is not. Something has to resolve that ambiguity, and if it is not a governed semantic layer then it is the model guessing — plausibly, fluently, and sometimes wrongly, with no signal to the person reading the answer.
Verdict
SQL — Adopt. The most durable interface in data, the best-supported, and the one LLMs generate most reliably. Everything else on this page is a complement to it or a wrapper over it.
DataFrame APIs — Adopt alongside SQL for the logic SQL expresses badly: iterative work, complex reshaping, anything that wants real control flow. Weaker on portability and governance.
Text-to-SQL / NL — Trial as an accelerator on top of a governed semantic layer, never as the layer itself. Lowest verifiability on the page.
Notebooks as a production pipeline — Hold. Excellent for exploration, structurally bad at testing (2.2) and reproducibility. Promote the logic out; do not schedule the notebook.
2. Positioning
These four sit at different points on one trade-off: how much the interface constrains you, and how much that constraint buys.
SQL is maximally constrained — declarative, set-oriented, no control flow — and every one of those constraints is what makes it verifiable, optimisable and portable. You describe the result; the engine decides how. That is why the same query runs on Snowflake, DuckDB and ClickHouse, and why a reviewer can reason about correctness without executing it. DataFrame APIs relax the constraint: you get variables, loops, functions and a host language's whole ecosystem, and you give up the optimiser's freedom and most of the portability. Text-to-SQL removes the constraint of knowing SQL, and with it the constraint that the question be unambiguous. Notebooks remove the constraint of linear execution, which is liberating in exploration and catastrophic in production.
| Dimension | SQL | DataFrame APIs | Text-to-SQL | Notebooks |
|---|---|---|---|---|
| You express | What you want | How to compute it | What you mean | Whatever, in any order |
| Ambiguity | None | None | Inherent | Execution order |
| Reviewable without running | Yes | Mostly | Only the generated SQL | No |
| Portable across engines | Largely | Framework-bound | Via the SQL it emits | No |
| Governance hooks | Native — views, RLS, masking | Application-level | Inherits from the layer beneath | Effectively none |
| LLMs generate it | Very well | Well | n/a — it is the LLM | Well, and shouldn't |
| Fails by | Getting verbose | Getting untestable | Being confidently wrong | Not reproducing |
The row worth sitting with is the last one. Every interface here fails, and only text-to-SQL fails silently. Verbose SQL is visibly verbose. An untestable DataFrame pipeline announces itself the first time someone tries to test it. A notebook that will not reproduce fails loudly on the next machine. But a text-to-SQL answer that quietly joined the wrong table returns a number, formatted nicely, with no indication that anything went wrong — and a business user has no way to tell. That asymmetry is the whole reason for the 2.6.
3. Radar criteria — the reasoning
Expressiveness
DataFrame APIs 4.6 — a full host language beats a query language for iterative and procedural logic. SQL 4.2: enormously capable within its paradigm, awkward outside it, and window functions plus CTEs cover more ground than sceptics expect. Notebooks 4.0, text-to-SQL 3.4, limited by what can be said unambiguously in a sentence.
Correctness & verifiability
SQL 4.7 — declarative, reviewable without execution, and a reviewer can reason about it statically. DataFrames 4.0. Notebooks 2.8: hidden state and out-of-order execution mean the code you see is not necessarily the code that ran. Text-to-SQL 2.6, the lowest score here, for the silent-failure reason above.
Approachability (inverted — higher means easier to learn)
Text-to-SQL 4.8, obviously — the entire proposition is that there is nothing to learn. Notebooks 4.2. SQL 3.8: easy to start, and genuinely hard to master past window functions. DataFrames 3.4, which asks for programming ability first.
Tooling & ecosystem
SQL 4.9, the highest score in this assessment. Every warehouse, every BI tool, every ORM, dbt, linters, formatters, and a hiring pool measured in millions. DataFrames 4.4, notebooks 4.0, text-to-SQL 3.4 and fragmenting.
Testability
SQL 4.4 — dbt tests, assertions, and the fact that a query is a pure function of its inputs. DataFrames 4.2, testable with ordinary unit tests. Text-to-SQL 2.8: you can test the generated SQL, not the generation. Notebooks 2.2, the lowest number on this page and the reason production notebooks are a Hold.
Portability
SQL 4.6 — dialect differences are real and mostly annoyance rather than obstacle; the same logic survives an engine migration. Text-to-SQL 3.8 inherits that via its output. DataFrames 3.6: pandas code does not run on Spark without a rewrite. Notebooks 2.8.
Performance ceiling
SQL 4.4 — a declarative query gives the optimiser the most freedom, which is why it wins at scale. DataFrames 4.3, close, with lazy frameworks like Polars and Spark narrowing it further. Notebooks 3.8, text-to-SQL 3.6 (generated SQL is rarely well-tuned).
Governance fit
SQL 4.7 — views, row-level security, column masking and grants are native concepts, so governance is enforced by the same engine that runs the query. DataFrames 3.6: enforcement moves into the application, where it is easier to bypass. Text-to-SQL 3.0, entirely dependent on what it generates against. Notebooks 2.6.
Collaboration
SQL 4.3 — reviewable in a pull request by someone who did not write it, which is the property that matters. DataFrames 3.8. Notebooks 3.4: notoriously bad in diffs. Text-to-SQL 3.4, since the artifact to review is the output, not the prompt.
Durability
SQL 4.9. It is fifty years old, it survived object databases, NoSQL, MapReduce and now LLMs, and each wave ended with SQL added back on top. DataFrames 4.2, text-to-SQL 3.4, notebooks 3.0. If you are choosing what to teach a team, this row is the one to weight.
4. Radar scorecard
How these scores are arrived at — the rings, the 0–5 scale, and the evidence rules — is written up in the radar methodology. This table and the chart below are generated from one file, scorecards.json: the source of truth, machine-readable, and kept separate so two copies of the same numbers cannot drift apart between editions. Last reviewed 2026-Q3.
| Criterion | SQL | Evidence | Risk → mitigation |
|---|---|---|---|
| Expressiveness | 4.2 | Declarative and set-oriented; reviewable without running | Verbosity → CTEs and dbt models, not clever nesting |
| Correctness & Verifiability | 4.7 | Pure function of inputs; statically reasonable | — |
| Approachability (inverted: higher = easier to learn) | 3.8 | Easy to start, hard past window functions | Skill ceiling → invest in training, it compounds |
| Tooling & Ecosystem | 4.9 | Every warehouse, BI tool, ORM, dbt; millions of practitioners | — |
| Testability | 4.4 | dbt tests and assertions; query-level unit testing | — |
| Portability | 4.6 | Survives engine migration; dialect gaps are annoyance | Dialect drift → SQLGlot or dbt macros |
| Performance Ceiling | 4.4 | Declarative gives the optimiser maximum freedom | — |
| Governance Fit | 4.7 | Views, RLS, masking and grants are native | — |
| Collaboration | 4.3 | Reviewable in a PR by someone who didn't write it | — |
| Durability | 4.9 | Fifty years; outlived every declared successor | — |
Comparator scores (same axis order) — DataFrame APIs: 4.6 / 4 / 3.4 / 4.4 / 4.2 / 3.6 / 4.3 / 3.6 / 3.8 / 4.2. Text-to-SQL / NL: 3.4 / 2.6 / 4.8 / 3.4 / 2.8 / 3.8 / 3.6 / 3 / 3.4 / 3.4. Notebooks as pipeline: 4 / 2.8 / 4.2 / 4 / 2.2 / 2.8 / 3.8 / 2.6 / 3.4 / 3.
5. The radar
Ten interface axes, Approachability inverted so higher is always better. SQL is the roundest shape on this radar — strong nearly everywhere, weakest only on approachability. Text-to-SQL is its inverse: the single highest approachability score and the lowest verifiability. Notebooks collapse at Testability (2.2), which is the number behind the Hold. Click any name in the legend to toggle it on or off — comparing two shapes at a time is far more legible than comparing four.
6. Workload-specific analysis
| Situation | Best fit | Notes |
|---|---|---|
| Transformations and metric definitions | SQL | Governed, testable, portable, reviewable. The default. |
| Iterative or procedural logic | DataFrames | Loops and branching are what SQL genuinely lacks. |
| ML feature engineering | DataFrames | Sits in the same language as the model code. |
| Exploration and hypothesis testing | Notebooks | Excellent here. This is the job they are good at. |
| Self-serve questions from business users | Text-to-SQL | Only over a governed semantic layer, with the SQL shown. |
| Anything a regulator will read | SQL | Lineage, review trail, and native access control. |
| Scheduled production pipeline | Not notebooks | 2.2 on testability. Promote the logic into a tested module. |
| NL over raw tables, no semantic layer | Hold | Confidently wrong answers with no signal to the reader. |
The trap: shipping natural-language analytics over raw tables because the demo was convincing. Text-to-SQL demos beautifully — someone asks "what was revenue last quarter", a number appears, the room is impressed. What the demo cannot show is the ambiguity the model resolved silently: which revenue, gross or net; which quarter, fiscal or calendar; which rows, including refunds or not. Over raw tables the model guesses, and it guesses fluently. The fix is not a better model — it is a semantic layer that makes the answer unambiguous before the question is asked, so the model resolves names rather than inventing joins. Then show the generated SQL, always. An answer nobody can check is not an answer, it is a claim.
7. Reference architecture
The shape that makes all four coexist: SQL as the substrate, a semantic layer as the contract, and natural language strictly as a client of that contract rather than a replacement for it.
graph LR
RAW[("Raw tables")] --> DBT["SQL transformations
dbt, tested"]
DBT --> MART[("Curated marts")]
MART --> SEM["Semantic layer
metrics defined once"]
SEM --> BI["BI dashboards"]
SEM --> NL["Natural language
text-to-SQL"]
NL -.->|"shows generated SQL"| USER["Business user"]
BI --> USER
MART --> DF["DataFrames
ML features, iterative work"]
DF --> ML["Model training"]
NB["Notebooks"] -.->|"explore, then promote"| DBT
NB -.->|"explore, then promote"| DF
GOV["RLS, masking, grants"] -.->|"enforced in-engine"| MART
Natural language is a client of the semantic layer, never of the raw tables — that is what turns an ambiguous question into a resolvable one. The notebook arrows point one way on purpose: explore in a notebook, then promote the logic into something tested. A notebook that becomes a scheduled job is how a 2.2 on testability enters production.
The pattern that makes text-to-SQL safe enough to ship — constrain what it can name, and show what it produced:
-- The semantic layer is the contract. "Revenue" means exactly one thing,
-- defined once, and the model resolves a NAME rather than inventing a join.
-- Without this, "what was revenue last quarter" has four defensible answers
-- and the LLM picks one without telling anyone.
create or replace view semantic.revenue_daily as
select
o.order_date as day,
c.region,
c.segment,
sum(o.gross_amount) as revenue_gross,
sum(o.gross_amount - coalesce(r.refund_amount, 0))
as revenue_net, -- the default
count(distinct o.order_id) as orders
from marts.fct_orders o
join marts.dim_customer c using (customer_id)
left join marts.fct_refunds r using (order_id)
where o.status = 'COMPLETED' -- excluded consistently, not per-question
group by 1, 2, 3;
-- Grant the NL tool this view and nothing else. It cannot join the wrong
-- table if it cannot see the wrong table — a permissions problem is easier
-- to reason about than a prompting problem.
grant select on semantic.revenue_daily to role nl_query_service;
8. POC plan (4 weeks)
- Week 1 — audit what your logic is written in today. Count transformations in SQL, in DataFrames, and in scheduled notebooks. That last number is your risk register, and it is usually higher than anyone expects.
- Week 2 — ask the ambiguity question. Take your five most-asked business questions and count the defensible answers to each. If "revenue" has four, no natural-language tool will help until the semantic layer does.
- Week 3 — test the honesty of the NL layer. Ask deliberately ambiguous questions and see whether it asks for clarification or guesses. Confidence without clarification is the failure mode; find it before your CFO does.
- Week 4 — set the policy per artifact type. Which logic must be SQL, where DataFrames are allowed, and what has to happen before a notebook is scheduled. Write it in the ADR; this is a standards decision more than a tooling one.
9. Final recommendation
Adopt SQL as the default and teach it properly. Adopt DataFrames for what SQL expresses badly. Trial natural language over a semantic layer. Hold notebooks out of production.
SQL earns the default on the axes that compound: it is reviewable without being run, portable across engines, natively governed, and supported by more tooling and more people than anything else in data. It also turned out to be the interface LLMs handle best — which means the honest read on the last three years is that AI made SQL more valuable, not less, by removing much of the typing while leaving the reading, reviewing and trusting exactly where they were. The skill that matters shifted from writing queries to evaluating them, and that is a SQL skill.
DataFrames belong in the stack for genuinely procedural work — feature engineering, iterative algorithms, anything that wants a loop. Reach for them when SQL starts fighting you, which is a real signal, and not before, because you are trading away portability and in-engine governance to get there.
Natural language is worth a trial and worth constraining hard. Put it over a governed semantic layer where metrics are defined once, grant it access to that layer and nothing beneath it, and always show the SQL it generated. Its 2.6 on verifiability is not a criticism of any particular product — it is a property of asking ambiguous questions of a system that answers fluently either way.
Notebooks are excellent at exploration and a Hold in production, on a 2.2 for testability and hidden execution state. Explore in a notebook, then promote the logic into something tested. Re-assess natural language when tools reliably ask a clarifying question instead of guessing — that single behaviour is what would move it from Trial toward Adopt, and it matters more than model quality.
References
The strongest evidence here is old, which is itself the argument for SQL's durability.
Research
- Codd, "A Relational Model of Data for Large Shared Data Banks", CACM 1970. Why declarative beat navigational, and why the argument has stayed settled for fifty years.
- Chamberlin & Boyce, "SEQUEL: A Structured English Query Language", 1974. The original design goal was approachability by non-programmers — the same goal text-to-SQL is chasing now.
- Gao et al., "Text-to-SQL Empowered by Large Language Models: A Benchmark Evaluation", PVLDB 17, 2024. Measured LLM text-to-SQL accuracy — the empirical basis for the verifiability score.
- Spider and BIRD. The standard text-to-SQL benchmarks; BIRD in particular shows how far real-world schemas sit from benchmark ones.
Primary sources
- dbt — semantic models. The layer natural language should be pointed at rather than at raw tables.
- Polars and Apache Arrow. The modern DataFrame lineage.
Deeper reading (blog)
The internals behind the scores:
- Advanced SQL Patterns — the window functions and CTEs that raise SQL's expressiveness ceiling.
- Text-to-SQL and the Semantic Layer — the deep-dive behind the Trial verdict.
- The Metrics Layer & Headless BI — defining a metric once, which is the prerequisite for safe NL.
- pandas vs Polars vs DuckDB vs Arrow — choosing within the DataFrame family.
- Analytics Engineering with dbt — SQL as software, which is what makes the testability score real.
- Radar: dbt and the transformation layer — the tooling around the interface.
Scores are my own architect-level judgment for the stated use case, calibrated to mid-2026 — not a vendor ranking. Interface axes, one inverted (Approachability). NOT comparable with the platform assessments. Re-score against your own POC numbers before you commit.