All skills
aws avatar

/redshift-guide

@53a7368

Amazon Redshift is NOT PostgreSQL — corrects PostgreSQL-derived LLM mistakes; covers Redshift-specific SQL, DDL, COPY/UNLOAD, system views, metadata discovery, and operational patterns. Applies ONLY when the task is about Redshift itself (cluster, Serverless workgroup, or Redshift SQL). Pushes back on: CREATE INDEX, string_agg, pg_catalog, text type, SERIAL, stl_query, LATERAL, RETURNING. Triggers on: Redshift SQL, Redshift CREATE TABLE, Redshift COPY/UNLOAD, slow Redshift query, Redshift permission denied, Redshift disk full, Redshift system views, QUALIFY, PIVOT, MERGE, Redshift Data API, Redshift WLM, concurrency scaling, Redshift resize, Redshift Spectrum external tables. Does NOT apply to (defer to that service's own skill): Amazon S3 storage/bucket policies, Athena or Glue queries/catalogs, data-lake or Iceberg work outside Redshift, Aurora, RDS, or DynamoDB — but S3/Glue ARE in scope for Redshift COPY, UNLOAD, or data-lake queries (external schemas/tables on S3).

Use this Skill: https://skilld.dev/gh/aws/agent-toolkit-for-aws/redshift-guide

This session only. Nothing lands on disk.

referencesredshift-sql-functions-types.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Redshift Functions & Data Types

Function mapping

PostgreSQL (wrong on Redshift) Redshift (correct)
string_agg(col, ',') LISTAGG(col, ',') WITHIN GROUP (ORDER BY col)
array_agg() / json_agg() Not supported — use SUPER type
NOW() GETDATE() / SYSDATE
regexp_matches() REGEXP_SUBSTR(), REGEXP_COUNT(), REGEXP_INSTR()
FILTER (WHERE ...) CASE WHEN ... END inside the aggregate
DISTINCT ON (col) ROW_NUMBER() OVER (PARTITION BY col ORDER BY ...) = 1
LATERAL join Correlated subquery
RETURNING Separate SELECT after the DML
ON CONFLICT MERGE INTO ... USING ... WHEN MATCHED / NOT MATCHED
SUBSTR(str, pos) on a table SUBSTRING() — SUBSTR is leader-node only
generate_series() for a date/number series joined to data Recursive CTE — generate_series is unsupported (may appear to work only in queries referencing no tables); it errors the moment it's joined to table data

Supported as-is (Oracle/T-SQL compat): NVL(a,b), NVL2(), DECODE(), COALESCE(), ILIKE, WITH RECURSIVE, window functions.

Date/number series (gap-filling) — use a recursive CTE, not generate_series

generate_series() is unsupported (may appear to work only in queries referencing no tables), so it fails when its output is joined against table data (the usual gap-fill case). Use WITH RECURSIVE:

WITH RECURSIVE dates(d) AS (
  SELECT CAST('2024-01-01' AS DATE)
  UNION ALL
  SELECT CAST(DATEADD(day, 1, d) AS DATE) FROM dates WHERE d < CAST('2024-12-31' AS DATE)
)
SELECT d FROM dates;              -- then LEFT JOIN your table on d to fill gaps

The recursive term must cast back to DATE — DATEADD returns TIMESTAMP, and Redshift requires the recursive column's type to match the anchor's exactly (otherwise: "Datatype mismatch in recursive CTE").

Data type mapping

PostgreSQL (wrong) Redshift (correct) Why
text VARCHAR(max) or VARCHAR(N) A text column is converted to VARCHAR(256). The DDL is accepted without error, but inserting more than 256 characters fails with value too long for type character varying(256) — it does not truncate. Specify the length you need
SERIAL / BIGSERIAL INT IDENTITY(1,1) / BIGINT IDENTITY(1,1) Auto-increment
jsonb / json SUPER Semi-structured, dot-notation access
int[] / boolean[] Not supported Use SUPER
bytea VARBYTE (a.k.a. VARBINARY) Binary
uuid CHAR(36) No native UUID type

Synonyms — both spellings are valid on Redshift, no rewrite needed:

Either form works Canonical Redshift name Note
NUMERIC(p,s) DECIMAL(p,s) Same type; max precision 38

Date/time functions

Unit-first argument order:

SELECT DATEADD(<datepart, identifier, no quotes>, <interval, integer, no quotes>, <ts, timestamp, no quotes>);
SELECT DATEDIFF(<datepart, identifier, no quotes>, <start, timestamp, no quotes>, <end, timestamp, no quotes>);
  • dateparts: year, month, week, day, hour, minute, second, millisecond, microsecond
  • DATEADD(day, -30, GETDATE()) — last 30 days; DATEADD(month, 3, ship_date).
  • DATEDIFF(day, start_ts, end_ts) returns a BIGINT count of crossed boundaries.
  • DATE_TRUNC('month', ts), EXTRACT(year FROM ts) / DATE_PART('year', ts) — same as PG.
  • GETDATE()/SYSDATE return TIMESTAMP; use TRUNC(GETDATE()) or CURRENT_DATE for DATE.

The left column below is leader-node-only and deprecated — it may still execute, but use the right-column replacement.

Instead of Use
AGE DATEDIFF
CURRENT_TIME / CURRENT_TIMESTAMP GETDATE() or SYSDATE
LOCALTIME / LOCALTIMESTAMP GETDATE() or SYSDATE
NOW GETDATE() or SYSDATE
ISFINITE (no replacement documented)

NOW() inside a materialized view resolves to the MV's creation timestamp, not the current time.

Examples

-- LISTAGG (not string_agg)
SELECT customer_id, LISTAGG(product, ', ') WITHIN GROUP (ORDER BY order_date) AS products
FROM orders GROUP BY customer_id;

-- Last-N-days filter
SELECT * FROM events WHERE event_ts >= DATEADD(day, -7, GETDATE());

Source: SKILL.md on GitHub

No alerts1mo3 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    This skill provides a comprehensive technical guide for managing Amazon Redshift, including SQL syntax, data loading, and automation recipes. It incorporates security best practices such as least privilege IAM roles and encryption, and includes helpful guardrails for high-risk operations.

  • Socket1mo

    No alerts

  • Snyk1mo

    Risk: LOW · No issues

Signed by skilld at 53a7368. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated last month
metadata
{
  "version": "1"
}

README badge

README badge for aws/agent-toolkit-for-aws/redshift-guide