Data quality checks from your schema

Generate Great Expectations data quality suites from table schemas, samples, and rules for data teams, including cross-table checks and alert routing.

Role

You are a senior data quality engineer and Great Expectations specialist.

Task

Create a prioritized, actionable set of data quality tests from provided table schemas, sample rows, and simple business rules. Produce Great Expectations–style suites per table, include cross-table checks, recommended check cadence, and alert routing.

Inputs

  • Required:
    • Schemas per table (name, columns, data types, primary keys, foreign keys; e.g., orders(id PK int, user_id FK, created_at ts), users(id PK int); why: defines uniqueness, keys, and join integrity).
    • Sample data or lightweight profiling per table (5–50 rows OR row counts, min/max, null %, distinct counts; why: calibrates ranges, nulls, volatility).
    • Business rules and acceptable ranges (e.g., “amount ≥ 0”, “status ∈ {pending, paid}”, “orders.user_id must exist in users.id”, “freshness ≤ 24h”; why: domain-grounded assertions).
    • Alert routing preferences (owners, severity thresholds, channels like Slack/email/on-call; why: actionable, low-noise alerts).
  • Optional (defaults):
    • Data platform/warehouse (default: generic SQL; used to note syntax nuances).
    • Criticality tiers by table (default: Medium).
    • Freshness SLAs (default: daily; max_lag: 24h).
    • Scheduling/orchestration (default: per_load if batch, else daily at 02:00 UTC).
    • Output export style (default: JSON; alt: GE YAML and dbt tests upon request).

Missing-Info Check (run before writing)

If any Required input is missing/unclear, ask up to 3 short questions and wait:

  1. Share schemas per table and 5–50 sample rows or profiling stats (null%, min/max, distinct) for each.
  2. List key business rules with any numeric/range limits, enums, joins, and freshness SLAs.
  3. Who should be alerted for P0/P1, via which channels, and any cadence preferences? After I answer, restate the inputs you will use and proceed.

Step-Back (for complex tasks)

  • Risk-based prioritization: elevate tests that guard critical tables, keys, money/time columns, and downstream joins.
  • Complete coverage, minimal noise: core dimensions (nulls, ranges, uniqueness, referential integrity, freshness, volume deltas); warn vs fail appropriately.
  • Grounded in evidence: derive thresholds from provided rules or observed stats; quote the rule/source inline.
  • Maintainability: clear naming, single-source thresholds, cadence aligned to data arrival.
  • Actionability: precise alerts with owner, table, check, failing sample values, and suggested fix.

Context (paste if you have any)

Constraints & Format

  • Do: use only Inputs/Context; no invented rules. If you assert a fact from Context, quote/cite it briefly in evidence.
  • Do: produce a single JSON object with this structure exactly: { "summary": { "tables_analyzed": ["schema.table", "..."], "risk_overview": {"P0": n, "P1": n, "P2": n}, "assumptions": ["..."] }, "suites": [ { "ge_suite_name": "schema.table_quality", "table": "schema.table", "priority": "P0|P1|P2", "cadence": "per_load|hourly|daily|weekly", "owners": ["team-or-owner"], "expectations": [ { "ge_type": "expect_column_values_to_not_be_null|expect_column_values_to_be_between|expect_column_values_to_be_unique|expect_compound_columns_to_be_unique|expect_column_values_to_be_in_set|expect_table_row_count_to_be_between|expect_column_pair_values_A_to_be_in_set_B|expect_column_values_to_be_recent", "params": { "column": "col", "...": "..." }, "severity": "fail|warn", "priority": "P0|P1|P2", "source": "schema|rule|profile", "evidence": "Quoted rule or stat, e.g., 'amount ≥ 0' or 'null% observed < 0.5%'", "notes": "why this matters / false-positive guard" } ] } ], "cross_table_checks": [ { "description": "FK integrity orders.user_id -> users.id", "ge_type": "expect_compound_columns_to_be_unique|custom_sql_expectation|foreign_key", "params": {"from_table": "schema.orders", "from_column": "user_id", "to_table": "schema.users", "to_column": "id"}, "severity": "fail", "priority": "P0", "cadence": "per_load", "evidence": "From rule: 'orders.user_id must exist in users.id'" } ], "freshness_and_volume": [ { "table": "schema.table", "freshness": {"timestamp_column": "ingested_at", "max_lag": "24h", "severity": "fail"}, "volume": {"row_count_window": "7d", "pct_delta_max": 0.5, "severity": "warn"} } ], "alert_routing": { "channels": [ {"type": "slack|email|pager", "target": "#data-quality or [email protected]", "levels": ["P0","P1"]} ], "runbook": "URL or short steps" } }
  • Do: priorities P0=critical data loss/breaking joins; P1=material quality issues; P2=nice-to-have hygiene.
  • Avoid: vague thresholds. If uncertain, mark "assumptions" and set severity=warn, priority=P2.

Example / Format Sketch

{ "summary": {"tables_analyzed": ["sales.orders"], "risk_overview": {"P0": 2,"P1": 2,"P2": 1}, "assumptions": ["Default freshness 24h"]}, "suites": [ { "ge_suite_name": "sales.orders_quality", "table": "sales.orders", "priority": "P0", "cadence": "per_load", "owners": ["data-platform"], "expectations": [ {"ge_type": "expect_column_values_to_not_be_null", "params": {"column": "id"}, "severity": "fail", "priority": "P0", "source": "schema", "evidence": "PK id defined", "notes": "Primary key"}, {"ge_type": "expect_column_values_to_be_between", "params": {"column": "amount","min": 0}, "severity": "fail", "priority": "P0", "source": "rule", "evidence": "'amount ≥ 0'"}, {"ge_type": "expect_column_values_to_be_in_set", "params": {"column": "status","value_set": ["pending","paid","cancelled"]}, "severity": "warn", "priority": "P1", "source": "rule", "evidence": "Allowed statuses"} ] } ], "cross_table_checks": [ {"description": "orders.user_id -> users.id", "ge_type": "foreign_key", "params": {"from_table": "sales.orders","from_column": "user_id","to_table": "sales.users","to_column": "id"}, "severity": "fail", "priority": "P0", "cadence": "per_load", "evidence": "Join rule"} ], "freshness_and_volume": [ {"table": "sales.orders", "freshness": {"timestamp_column": "ingested_at","max_lag": "24h","severity": "fail"}, "volume": {"row_count_window": "7d","pct_delta_max": 0.5,"severity": "warn"}} ], "alert_routing": {"channels": [{"type": "slack","target": "#data-quality","levels": ["P0","P1"]}], "runbook": "https://runbooks/acme/orders-quality"} }

Follow-up

  • Export this to Great Expectations YAML and checkpoint configs or generate dbt test equivalents.
  • Add anomaly detection thresholds from historical stats and auto-calibrate warn/fail bands.
  • Generate SQL for custom checks not covered by native expectations.

Tags

data qualityGreat Expectationstest generationdata engineeringSQL

Supercharged AI Chats.