Does DynamoDB support SQL?

Partly. DynamoDB supports PartiQL, a SQL-compatible query language for SELECT, INSERT, UPDATE, and DELETE statements. It is not full SQL: there are no JOINs, no GROUP BY, and no arbitrary aggregations, and efficient queries still require targeting the primary key or an index. If you want those missing pieces, DynoTable's SQL Workbench runs real JOIN, GROUP BY, and aggregate queries over your DynamoDB tables from the desktop.

What PartiQL gives you

A familiar SQL syntax for the four data operations. You can write SELECT * FROM "Orders" WHERE ... instead of constructing low-level API calls, which is convenient and readable.

What it does not give you

  • No JOINs — DynamoDB is nonrelational; you denormalize instead.
  • No GROUP BY / aggregates — grouping and summing happen in your application.
  • No free-form scans for cheap — a SELECT without a key condition still runs a Scan and costs accordingly.

Where the parser stops

These are not features you can reach with different syntax. Run them and the statement never gets as far as reading an item:

SELECT "region", SUM("total") FROM "Orders" GROUP BY "region"
  ValidationException: Unsupported clause: GROUP BY

SELECT COUNT(*) FROM "Orders"
  ValidationException: Unexpected path component at 1:8:5

SELECT SUM("total") FROM "Orders"
  ValidationException: Unexpected path component at 1:8:3

SELECT DISTINCT "region" FROM "Orders"
  ValidationException: Unsupported token in expression: DISTINCT

Look at what the aggregate errors say. There is no aggregate function for the parser to turn down, so COUNT(*) is read as an attribute path and falls over on the *, at column 8. That is how thin the SQL surface is.

ORDER BY is the one to know about, because it looks like it works:

SELECT * FROM "Orders" WHERE "pk" = 'U#1' ORDER BY "total"
  ValidationException: Variable reference total in ORDER BY clause must be part of the primary key

You can sort by the sort key, ascending or descending, and by nothing else. Sorting by any other attribute is your application's job, after the read.

The mental model

Think of PartiQL as a syntax layer over DynamoDB's existing Query, Scan, and write operations; the same access-pattern rules apply underneath.

Real SQL (JOIN, GROUP BY, aggregates) with DynoTable

PartiQL stops at single-table SELECT. DynoTable's SQL Workbench goes further: it runs actual JOIN, GROUP BY, and aggregate functions (COUNT, SUM, AVG, MIN, MAX) over your DynamoDB tables. It reads the items through the normal DynamoDB API, then executes the relational part of the query in the client: SQL within DynamoDB's access-pattern rules, since each join still reads through a real key or index. So the three things PartiQL can't do, you write as one statement:

SELECT   c.region, COUNT(*) AS orders, SUM(o.total) AS revenue
FROM     Orders o
JOIN     Customers c ON o.customerId = c.id
GROUP BY c.region

It stays honest about the underlying constraints (an unbounded join is an unbounded read), so the fastest queries are the ones whose join or WHERE hits a partition key or index. Full detail in SQL for DynamoDB and the product manual at /docs/dynamodb-sql-workbench.

Prototype the PartiQL side of the same data model with the DynamoDB query builder — it emits partition-scoped Query programs that stay on the efficient path PartiQL SELECT uses when a key condition is present.

Go deeper

Compare the two in PartiQL vs SQL, see PartiQL examples, and read SQL for DynamoDB. Download DynoTable to write PartiQL, and real JOIN, GROUP BY, and aggregates, against your tables.

References

Last verified 2026-07-13 against the official AWS documentation linked above.

Every ValidationException above was reproduced 2026-07-28 against DynamoDB Local 3.3.0 via @aws-sdk/client-dynamodb 3.1095.0 and is quoted verbatim, column offsets included.

Work with DynamoDB without the Console

A fast DynamoDB desktop client that runs the real SQL DynamoDB can’t — JOINs, GROUP BY, aggregates — with visual editing and an AI agent on your own Bedrock keys.

Free 30-day trial, no credit card — then the Free plan with no time limit.