Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124

Nothing. Ok, I should probably write a bit more than that.
Nothing replaces SQL outright. Instead, three complementary layers are emerging around SQL. It will likely be with us forever, but it’s interesting to understand what alternatives exist and why.
Implication: SQL is expanding to cover more modalities (graphs, JSON). The “replacement” narrative misunderstands the standard’s trajectory. (Wikipédia)
Malloy is an open-source language that describes data relationships and metrics once, then generates efficient SQL for multiple backends (BigQuery, Snowflake, Postgres, Trino, DuckDB). It aims to reduce verbose, error-prone SQL by encoding business semantics and reusable patterns. (GitHub, Malloy Data). Here is a simple example using the Malloy Python library.
%%malloy_model flights
source: airports is duckdb.table('../data/airports.parquet') extend {
primary_key: code
measure: airport_count is count()
}
source: flights is duckdb.table('../data/flights.parquet') extend {
rename:
origin_code is origin
destination_code is destination
join_one: origin is airports with origin_code
join_one: destination is airports with destination_code
measure:
flight_count is count()
destination_count is destination.count()
origin_count is origin.count()
}PRQL is a modern, composable, pipeline-style relational language that compiles to SQL, adding variables, functions, and clearer dataflow syntax. It targets any SQL database, and has ecosystem bindings (e.g., R). (GitHub, PRQL, CRAN)
Why it matters: PRQL improves authoring ergonomics while preserving SQL compatibility — a likely pattern for many teams that want nicer syntax, not a new engine. (GitHub)
Here is a simple SQL example:
SELECT name, salary, hire_date
FROM employees
WHERE department = 'Engineering'
AND salary > 80000
ORDER BY salary
LIMIT 10;And the same code written in PRQL
from employees
filter department == "Engineering"
filter salary > 80000
select {name, salary, hire_date}
sort salary
take 10SQL++ generalizes SQL for nested JSON, with Couchbase’s N1QL a commercial implementation; it brings path navigation, arrays, and heterogeneity into a SQL-like grammar. Academic lineage comes via AsterixDB. (docs.couchbase.com, asterixdb.apache.org, Couchbase, odbms.org)
Bottom line: These languages don’t kill SQL; they augment or transpile to it so you keep portability and optimizer maturity.
There is a simple SQL example:
SELECT p.name, p.age, a.city, COUNT(h.hobby_id) as hobby_count
FROM people p
JOIN addresses a ON p.id = a.person_id
JOIN person_hobbies ph ON p.id = ph.person_id
JOIN hobbies h ON ph.hobby_id = h.id
WHERE p.age > 25
AND a.country = 'USA'
AND h.name = 'coding'
GROUP BY p.id, p.name, p.age, a.city
ORDER BY p.age DESC
LIMIT 10;And the same code written in SQL++:
SELECT p.name, p.age, p.address.city, ARRAY_LENGTH(p.hobbies) as hobby_count
FROM people p
WHERE p.age > 25
AND p.address.country = "USA"
AND ANY hobby IN p.hobbies SATISFIES hobby = "coding" END
ORDER BY p.age DESC
LIMIT 10;Remember that SQL++ is designed for NoSQL databases with nested JSON as shown below. Meaning that the joins necessary in SQL do not apply:
{
"name": "Alice",
"age": 30,
"address": {
"city": "San Francisco",
"country": "USA"
},
"hobbies": ["coding", "hiking", "photography"]
}Take: rather than a replacement, we now have two interoperable standards (SQL/PGQ for relational, GQL for native graph). Expect dual-stack systems and cross-compilers over time. (Wikipédia)
Here is a simple SQL example:
SELECT p.name, p.age, c.name AS company, COUNT(ps.skill_id) AS skill_count
FROM people p
JOIN employment e ON p.id = e.person_id
JOIN companies c ON e.company_id = c.id
JOIN person_skills ps ON p.id = ps.person_id
JOIN skills s ON ps.skill_id = s.id
WHERE p.age > 25
AND c.country = 'USA'
AND EXISTS (
SELECT 1 FROM person_skills ps2
JOIN skills s2 ON ps2.skill_id = s2.id
WHERE ps2.person_id = p.id AND s2.name = 'coding'
)
GROUP BY p.id, p.name, p.age, c.name
ORDER BY p.age DESC
LIMIT 10;And the same code wrotten in ISO GQL:
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
WHERE p.age > 25
AND c.country = "USA"
AND (p)-[:HAS_SKILL]->(:Skill {name: "coding"})
RETURN p.name, p.age, c.name AS company,
COUNT((p)-[:HAS_SKILL]->()) AS skill_count
ORDER BY p.age DESC
LIMIT 10Substrait defines a cross-language, unambiguous representation for relational compute (logical/physical plans). Systems can exchange plans independent of a specific query language string, enabling consistent optimization and portability across engines. (substrait.io, Medium)
Why it matters: If the plan is portable, “universal language” pressure weakens. You can author in SQL, PRQL, Malloy, or a UI and still ship a common plan to Spark, DuckDB, DataFusion, etc. (substrait.io)
dbt Semantic Layer (MetricFlow) formalizes business metrics (definitions, grains, time bindings) and compiles queries dynamically for the underlying engine. This makes metrics the interface rather than raw SQL – a different kind of “universal language” that business tools can call consistently. (docs.getdbt.com, dbt Labs, GitHub)
Why it matters: When consumers ask for revenue_7d instead of writing joins, the “universal language” becomes a metrics API that happens to emit SQL under the hood. (dbt Labs)
semantic_models:
- name: order_item
defaults:
agg_time_dimension: ordered_at
description: |
Items contained in each order. The grain of the table is one row per order item.
model: ref('order_items')For more information on dbt (Data Built Tool), please see the blog post below.
Python/R DataFrames (Ibis, Pandas) are effectively a lingua franca for developers. Engines like DuckDB run SQL directly on DataFrames or provide relational APIs, while Ibis offers a portable DataFrame API that targets multiple SQL engines. (DuckDB, GitHub)
Net effect: The surface language may be Pythonic, but execution often compiles to SQL or a relational plan — reinforcing SQL as the substrate. (DuckDB)