Documentation Index

Fetch the complete documentation index at: https://docs.validatar.com/llms.txt

Use this file to discover all available pages before exploring further.

Multi-Row Test Results Tables

Prev Next

Overview

Multi-row test results are stored across four related tables that work together to represent the full result set. Unlike single-value tests (which store everything in one table), multi-row tests use a normalized "long format" structure that separates column definitions, row-level results, key values, and comparison values into separate tables.

This design supports tests with any number of columns and rows without requiring a fixed schema. The trade-off is that querying specific column values requires pivoting the data.

The Four Tables

TEST_EXECUTION_TABLE_COLUMNS     — defines which columns exist for an execution
        │
        â–¼
TEST_EXECUTION_TABLE_RESULTS     — one row per result row (pass/fail per row)
        │
        ├──── TEST_EXECUTION_TABLE_RESULT_KEYS    — key column values (long format)
        │
        └──── TEST_EXECUTION_TABLE_RESULT_VALUES  — value column comparisons (long format)

TEST_EXECUTION_TABLE_COLUMNS

Defines the column structure for a test execution — what columns exist, their roles, and aggregate pass/fail counts.

Column Type Description
TEST_EXECUTION_ID NUMBER Execution ID
TEST_ID NUMBER Test ID
TEST_VERSION_ID NUMBER Test version ID
COLUMN_SEQUENCE NUMBER Column position (used to join to KEYS and VALUES tables)
TEST_SET_COLUMN_NAME VARCHAR Column name from the test (source) dataset
TEST_SET_COLUMN_SEQUENCE NUMBER Original sequence in the test dataset
TEST_SET_COLUMN_TYPE_ID NUMBER Column type code
TEST_SET_COLUMN_TYPE_NAME VARCHAR "Key" or "Value"
TEST_SET_COLUMN_ROLE_ID NUMBER Column role code
TEST_SET_COLUMN_ROLE_NAME VARCHAR Column role (e.g., "Key", "Source Value", "Target Value")
CONTROL_SET_COLUMN_NAME VARCHAR Corresponding column name in the control dataset
CONTROL_SET_COLUMN_SEQUENCE NUMBER Sequence in the control dataset
CONTROL_SET_COLUMN_TYPE_ID NUMBER Control column type code
CONTROL_SET_COLUMN_TYPE_NAME VARCHAR Control column type name
CONTROL_SET_COLUMN_ROLE_ID NUMBER Control column role code
CONTROL_SET_COLUMN_ROLE_NAME VARCHAR Control column role name
PASSED_COUNT NUMBER Rows that passed for this column
FAILED_COUNT NUMBER Rows that failed for this column
ERROR_COUNT NUMBER Rows that errored for this column

TEST_EXECUTION_TABLE_RESULTS

One row per result row in the test execution. Contains the overall evaluation for each row.

Column Type Description
TEST_EXECUTION_ID NUMBER Execution ID
TEST_ID NUMBER Test ID
TEST_VERSION_ID NUMBER Test version ID
ROW_INDEX NUMBER Row position (1-based)
COVERAGE_FLAG NUMBER 3 = Matched, 1 = Unmatched Test Only, 2 = Unmatched Control Only
EVALUATION_RESULT_ID NUMBER 24 = Passed, 25 = Failed, 26 = Error
EVALUATION_RESULT_NAME VARCHAR "PASSED", "FAILED", or "ERROR"
PASSED_VALUE_COUNT NUMBER Number of value columns that passed for this row
FAILED_VALUE_COUNT NUMBER Number of value columns that failed
ERROR_VALUE_COUNT NUMBER Number of value columns that errored
KEY_HASH VARCHAR Hash of the combined key values for this row

TEST_EXECUTION_TABLE_RESULT_KEYS

Stores the actual key column values for each result row in long format (one row per key column per result row).

Column Type Description
TEST_EXECUTION_ID NUMBER Execution ID
ROW_INDEX NUMBER Row position — join to TABLE_RESULTS
COLUMN_SEQUENCE NUMBER Which column this value belongs to — join to TABLE_COLUMNS
RESULT_KEY VARCHAR The actual key value (stored as string regardless of original type)
OVERFLOW_FLAG NUMBER 0 = normal, 1 = value truncated

TEST_EXECUTION_TABLE_RESULT_VALUES

Stores the comparison values for each value column per result row in long format.

Column Type Description
TEST_EXECUTION_ID NUMBER Execution ID
ROW_INDEX NUMBER Row position — join to TABLE_RESULTS
COLUMN_SEQUENCE NUMBER Which column — join to TABLE_COLUMNS
NUMERIC_SOURCE_VALUE DECIMAL(27,8) Numeric value from source
NUMERIC_TARGET_VALUE DECIMAL(27,8) Numeric value from target
ACTUAL_DIFFERENCE DECIMAL(27,8) Source minus target
ABSOLUTE_DIFFERENCE DECIMAL(27,8) Absolute difference
PERCENT_DIFFERENCE DECIMAL(18,9) Percentage difference
EVALUATION_RESULT_ID NUMBER 24 = Passed, 25 = Failed, 26 = Error
EVALUATION_RESULT_NAME VARCHAR "PASSED", "FAILED", or "ERROR"
STRING_SOURCE_VALUE VARCHAR String value from source
STRING_TARGET_VALUE VARCHAR String value from target
DATE_SOURCE_VALUE VARCHAR Date value from source
DATE_TARGET_VALUE VARCHAR Date value from target
OVERFLOW_FLAG NUMBER 0 = normal, 1 = truncated

Join Pattern

All four tables join on TEST_EXECUTION_ID. Within an execution:

  • TABLE_RESULTS + TABLE_RESULT_KEYS join on ROW_INDEX
  • TABLE_RESULTS + TABLE_RESULT_VALUES join on ROW_INDEX
  • TABLE_COLUMNS defines what COLUMN_SEQUENCE means in KEYS and VALUES
-- Full join pattern
SELECT
    cols.TEST_SET_COLUMN_NAME,
    cols.TEST_SET_COLUMN_TYPE_NAME,
    res.ROW_INDEX,
    res.EVALUATION_RESULT_NAME AS ROW_RESULT,
    keys.RESULT_KEY,
    vals.NUMERIC_SOURCE_VALUE,
    vals.NUMERIC_TARGET_VALUE,
    vals.EVALUATION_RESULT_NAME AS VALUE_RESULT
FROM RESULTS.TEST_EXECUTION_TABLE_COLUMNS cols
LEFT JOIN RESULTS.TEST_EXECUTION_TABLE_RESULTS res
    ON res.TEST_EXECUTION_ID = cols.TEST_EXECUTION_ID
LEFT JOIN RESULTS.TEST_EXECUTION_TABLE_RESULT_KEYS keys
    ON keys.TEST_EXECUTION_ID = cols.TEST_EXECUTION_ID
    AND keys.ROW_INDEX = res.ROW_INDEX
    AND keys.COLUMN_SEQUENCE = cols.COLUMN_SEQUENCE
LEFT JOIN RESULTS.TEST_EXECUTION_TABLE_RESULT_VALUES vals
    ON vals.TEST_EXECUTION_ID = cols.TEST_EXECUTION_ID
    AND vals.ROW_INDEX = res.ROW_INDEX
    AND vals.COLUMN_SEQUENCE = cols.COLUMN_SEQUENCE
WHERE cols.TEST_EXECUTION_ID = 3913134;

Pivoting Results into a Wide Format

Because key and value data is stored in long format (one row per column per result row), you typically need to pivot it into a human-readable wide format. The pivot pattern uses conditional aggregation:

Pivot Key Columns

-- First, identify the column sequences for your execution
SELECT COLUMN_SEQUENCE, TEST_SET_COLUMN_NAME, TEST_SET_COLUMN_TYPE_NAME
FROM RESULTS.TEST_EXECUTION_TABLE_COLUMNS
WHERE TEST_EXECUTION_ID = 3913134
ORDER BY COLUMN_SEQUENCE;

-- Then pivot the keys
SELECT
    ROW_INDEX,
    MAX(CASE WHEN COLUMN_SEQUENCE = 1 THEN RESULT_KEY END) AS KEY_COL_1,
    MAX(CASE WHEN COLUMN_SEQUENCE = 2 THEN RESULT_KEY END) AS KEY_COL_2,
    MAX(CASE WHEN COLUMN_SEQUENCE = 3 THEN RESULT_KEY END) AS KEY_COL_3
FROM RESULTS.TEST_EXECUTION_TABLE_RESULT_KEYS
WHERE TEST_EXECUTION_ID = 3913134
GROUP BY ROW_INDEX
ORDER BY ROW_INDEX;

Pivot Value Columns with Source/Target

SELECT
    ROW_INDEX,
    MAX(CASE WHEN COLUMN_SEQUENCE = 4 THEN NUMERIC_SOURCE_VALUE END) AS COL4_SOURCE,
    MAX(CASE WHEN COLUMN_SEQUENCE = 4 THEN NUMERIC_TARGET_VALUE END) AS COL4_TARGET,
    MAX(CASE WHEN COLUMN_SEQUENCE = 4 THEN EVALUATION_RESULT_NAME END) AS COL4_RESULT,
    MAX(CASE WHEN COLUMN_SEQUENCE = 5 THEN NUMERIC_SOURCE_VALUE END) AS COL5_SOURCE,
    MAX(CASE WHEN COLUMN_SEQUENCE = 5 THEN NUMERIC_TARGET_VALUE END) AS COL5_TARGET,
    MAX(CASE WHEN COLUMN_SEQUENCE = 5 THEN EVALUATION_RESULT_NAME END) AS COL5_RESULT
FROM RESULTS.TEST_EXECUTION_TABLE_RESULT_VALUES
WHERE TEST_EXECUTION_ID = 3913134
GROUP BY ROW_INDEX
ORDER BY ROW_INDEX;

Complete Pivot with Keys and Values Joined

WITH pivoted_keys AS (
    SELECT
        ROW_INDEX,
        MAX(CASE WHEN COLUMN_SEQUENCE = 1 THEN RESULT_KEY END) AS ORDERKEY,
        MAX(CASE WHEN COLUMN_SEQUENCE = 2 THEN RESULT_KEY END) AS PARTKEY
    FROM RESULTS.TEST_EXECUTION_TABLE_RESULT_KEYS
    WHERE TEST_EXECUTION_ID = 3913134
    GROUP BY ROW_INDEX
),
pivoted_values AS (
    SELECT
        ROW_INDEX,
        MAX(CASE WHEN COLUMN_SEQUENCE = 3 THEN NUMERIC_SOURCE_VALUE END) AS AMOUNT_SOURCE,
        MAX(CASE WHEN COLUMN_SEQUENCE = 3 THEN NUMERIC_TARGET_VALUE END) AS AMOUNT_TARGET,
        MAX(CASE WHEN COLUMN_SEQUENCE = 3 THEN EVALUATION_RESULT_NAME END) AS AMOUNT_RESULT
    FROM RESULTS.TEST_EXECUTION_TABLE_RESULT_VALUES
    WHERE TEST_EXECUTION_ID = 3913134
    GROUP BY ROW_INDEX
)
SELECT
    k.ORDERKEY,
    k.PARTKEY,
    v.AMOUNT_SOURCE,
    v.AMOUNT_TARGET,
    v.AMOUNT_RESULT,
    r.EVALUATION_RESULT_NAME AS ROW_RESULT
FROM pivoted_keys k
JOIN pivoted_values v ON v.ROW_INDEX = k.ROW_INDEX
JOIN RESULTS.TEST_EXECUTION_TABLE_RESULTS r
    ON r.TEST_EXECUTION_ID = 3913134
    AND r.ROW_INDEX = k.ROW_INDEX
ORDER BY k.ROW_INDEX;

Example Queries

Find All Failed Rows for an Execution

SELECT
    r.ROW_INDEX,
    r.EVALUATION_RESULT_NAME,
    r.FAILED_VALUE_COUNT,
    r.COVERAGE_FLAG
FROM RESULTS.TEST_EXECUTION_TABLE_RESULTS r
WHERE r.TEST_EXECUTION_ID = 3913134
    AND r.EVALUATION_RESULT_NAME = 'FAILED'
ORDER BY r.ROW_INDEX;

Unmatched Rows (Rows in Source but Not Target)

SELECT
    r.ROW_INDEX,
    k.COLUMN_SEQUENCE,
    c.TEST_SET_COLUMN_NAME,
    k.RESULT_KEY
FROM RESULTS.TEST_EXECUTION_TABLE_RESULTS r
JOIN RESULTS.TEST_EXECUTION_TABLE_RESULT_KEYS k
    ON k.TEST_EXECUTION_ID = r.TEST_EXECUTION_ID
    AND k.ROW_INDEX = r.ROW_INDEX
JOIN RESULTS.TEST_EXECUTION_TABLE_COLUMNS c
    ON c.TEST_EXECUTION_ID = r.TEST_EXECUTION_ID
    AND c.COLUMN_SEQUENCE = k.COLUMN_SEQUENCE
WHERE r.TEST_EXECUTION_ID = 3913134
    AND r.COVERAGE_FLAG = 1  -- Test-only (unmatched in source)
ORDER BY r.ROW_INDEX, k.COLUMN_SEQUENCE;

Row Count Summary by Execution

SELECT
    te.TEST_NAME,
    te.DATE_COMPLETED,
    COUNT(*) AS TOTAL_ROWS,
    SUM(CASE WHEN r.EVALUATION_RESULT_NAME = 'PASSED' THEN 1 ELSE 0 END) AS PASSED_ROWS,
    SUM(CASE WHEN r.EVALUATION_RESULT_NAME = 'FAILED' THEN 1 ELSE 0 END) AS FAILED_ROWS,
    SUM(CASE WHEN r.COVERAGE_FLAG = 1 THEN 1 ELSE 0 END) AS UNMATCHED_SOURCE,
    SUM(CASE WHEN r.COVERAGE_FLAG = 2 THEN 1 ELSE 0 END) AS UNMATCHED_TARGET
FROM REPOSITORY.VW_DATASET_TEST_EXECUTIONS te
JOIN RESULTS.TEST_EXECUTION_TABLE_RESULTS r
    ON r.TEST_EXECUTION_ID = te.TEST_EXECUTION_ID
WHERE te.LATEST_TEST_EXECUTION_INDEX = 1
    AND te.TEST_NAME = 'Value Comparison - LINEITEM'
GROUP BY te.TEST_NAME, te.DATE_COMPLETED;

Coverage Flag Reference

COVERAGE_FLAG Meaning
1 Unmatched — row exists only in the test (source) dataset
2 Unmatched — row exists only in the control (target) dataset
3 Matched — row exists in both datasets and was compared

Databricks Notes

  • The pivot pattern using MAX(CASE WHEN ... END) is identical in Databricks SQL
  • Databricks may have different internal metadata columns in place of SF_DATE_CREATED and SF_IMPORT_FILENAME
  • For very large result sets, consider filtering on COVERAGE_FLAG or specific COLUMN_SEQUENCE values before pivoting to improve performance