PostgreSQL guide

Turn questions into PostgreSQL SQL.

PostgreSQL gives reporting queries expressive date, aggregate and row-selection tools. Ask for PostgreSQL explicitly so the generated SQL uses the functions your server understands.

Try TTSQL free

Before connecting PostgreSQL

Prepare a PostgreSQL host, port, database name, username and password. TTSQL's PostgreSQL adapter uses Postgrex and supports schema discovery. The server must be reachable from the TTSQL deployment, with authentication and TLS settings appropriate to your environment.

Use an account with only the table access your task needs. PostgreSQL schemas are namespaces within a database; record the intended schema when identically named tables exist in several schemas.

Give the prompt the right dialect and context

Unquoted PostgreSQL identifiers fold to lowercase. Double quotes preserve exact case, so customer_id and "Customer_ID" can be different columns. Single quotes delimit string values.

Specify whether a timestamp is stored with or without a time zone and which zone defines a reporting day. These teaching examples use UTC values in a timestamp without time zone. A timestamptz month bucket follows the session time zone unless the query converts it explicitly.

Schema used in these examples

customers(id INTEGER PRIMARY KEY, name TEXT, country TEXT); orders(id INTEGER PRIMARY KEY, customer_id INTEGER REFERENCES customers(id), ordered_at TIMESTAMP, status TEXT, total DECIMAL(12,2)). Each order has one customer. total is the order amount in a single reporting currency; paid means recognized revenue in this teaching dataset. Timestamps use UTC. These are example tables, not tables TTSQL creates.

Translate TEXT and TIMESTAMP to equivalent column types for your engine. Use your own database, schema and table qualifiers. Each example states its reporting grain and sorting rule.

Review these PostgreSQL details

DISTINCT ON requires its expressions to match the leftmost ORDER BY expressions. Add a tie-breaker such as order ID whenever the requested latest timestamp is not unique.

A LIMIT caps returned rows, not necessarily work done. An aggregate or sort can scan a large input before applying the limit. Use EXPLAIN to inspect a plan and reserve EXPLAIN ANALYZE for queries you are prepared to execute.

Generate, review, then choose whether to run

Select the matching database type and confirm your project's schema context before generating. Review the returned SQL against the schema and the metric you intended. A successful connection test does not prove that every table or operation is authorized.

TTSQL's POST /api/v1 endpoint generates SQL and returns executed: false. Query execution is a separate manual Run action in the workspace, subject to the configured connection and policies. The examples below are educational SELECT statements, not live results from your database.

Official PostgreSQL references

Check your engine version and account configuration when adapting a function or connection setting.

Worked SQL examples

Read the sample schema and assumptions alongside each query. Adapt names, dates, and definitions to your own database before running SQL.

01 / PostgreSQL

Bucket paid revenue with DATE_TRUNC

Show paid revenue by calendar month in the stored UTC timestamps, oldest month first.

SELECT DATE_TRUNC('month', ordered_at)::date AS month,
       SUM(total) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY 1
ORDER BY 1;

DATE_TRUNC buckets timestamps into months and the date cast gives a readable month-start value. This returns months containing paid orders. For a chart that must show zero-activity months, join the aggregate to a calendar table or generate_series.

02 / PostgreSQL

Choose one latest order with DISTINCT ON

Show each purchasing customer's latest paid order ID and total. Resolve equal timestamps by the largest order ID. Sort by customer ID.

SELECT DISTINCT ON (customer_id) customer_id, id, total
FROM orders
WHERE status = 'paid'
ORDER BY customer_id, ordered_at DESC, id DESC;

PostgreSQL DISTINCT ON keeps the first row of each customer group in the specified order. The ID tie-breaker makes the answer stable when two orders share a timestamp. MAX(ordered_at) alone would not identify a unique order total.

03 / PostgreSQL

Count each status with FILTER

For every customer with an order, show paid and cancelled order counts, ordered by customer ID.

SELECT customer_id,
       COUNT(*) FILTER (WHERE status = 'paid') AS paid_orders,
       COUNT(*) FILTER (WHERE status = 'cancelled') AS cancelled_orders
FROM orders
GROUP BY customer_id
ORDER BY customer_id;

FILTER gives each aggregate its own condition without discarding other statuses from the input. Customers without any order are absent because orders is the starting table. If you turn these counts into a percentage, define the denominator and guard division by zero.

Answers before you connect a database.

Does selecting PostgreSQL guarantee a working database connection?

No. SQL generation uses the project dialect and schema, while connection and execution also depend on deployment prerequisites, credentials, network access and database permissions. Complete the prerequisites described in this guide.

Does the TTSQL API execute PostgreSQL queries?

No. POST /api/v1 generates SQL and returns executed: false. Review the query; a separate manual Run action is available in the workspace when the connection and policies allow it.

Bring your next question to TTSQL.

Start with one PostgreSQL project and 20 free requests a day. Explore your data, build a report, or integrate the API.