> ## Documentation Index
> Fetch the complete documentation index at: https://docs.maia.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Detect Changes

export const ComponentMetadata = ({warehouses, unsupportedWarehouses = [], componentType, connectionInputs, connectionOutputs}) => {
  const allWarehouses = [...warehouses.map(w => ({
    name: w,
    supported: true
  })), ...unsupportedWarehouses.map(w => ({
    name: w,
    supported: false
  }))];
  return <div style={{
    background: 'var(--colors-background-light, #f9fafb)',
    border: '1px solid var(--colors-border-default, #e5e7eb)',
    borderRadius: '12px',
    padding: '20px 28px',
    marginBottom: '28px',
    boxShadow: '0 1px 4px rgba(0,0,0,0.10)'
  }}>
      <table style={{
    width: '100%',
    borderCollapse: 'collapse'
  }}>
        <tbody>
          <tr>
            <td style={{
    fontWeight: '600',
    paddingRight: '32px',
    paddingBottom: '14px',
    whiteSpace: 'nowrap',
    verticalAlign: 'middle',
    width: '180px'
  }}>Project Availability</td>
            <td style={{
    paddingBottom: '14px',
    verticalAlign: 'middle'
  }}>
              <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    gap: '8px'
  }}>
                {allWarehouses.map((w, i) => <span key={i} style={{
    background: w.supported ? '#dcfce7' : '#fee2e2',
    color: w.supported ? '#15803d' : '#b91c1c',
    border: `1px solid ${w.supported ? '#bbf7d0' : '#fca5a5'}`,
    borderRadius: '9999px',
    padding: '3px 12px',
    fontSize: '0.85rem',
    fontWeight: '500',
    whiteSpace: 'nowrap'
  }}>
                    {w.name} {w.supported ? '✅' : '❌'}
                  </span>)}
              </div>
            </td>
          </tr>
          <tr>
            <td style={{
    fontWeight: '600',
    paddingRight: '32px',
    paddingBottom: '14px',
    whiteSpace: 'nowrap',
    verticalAlign: 'middle'
  }}>Component Type</td>
            <td style={{
    paddingBottom: '14px',
    verticalAlign: 'middle'
  }}>{componentType}</td>
          </tr>
          <tr>
            <td style={{
    fontWeight: '600',
    paddingRight: '32px',
    paddingBottom: '14px',
    whiteSpace: 'nowrap',
    verticalAlign: 'middle'
  }}>Connection Inputs</td>
            <td style={{
    paddingBottom: '14px',
    verticalAlign: 'middle'
  }}>{connectionInputs}</td>
          </tr>
          <tr>
            <td style={{
    fontWeight: '600',
    paddingRight: '32px',
    whiteSpace: 'nowrap',
    verticalAlign: 'middle'
  }}>Connection Outputs</td>
            <td style={{
    verticalAlign: 'middle'
  }}>{connectionOutputs}</td>
          </tr>
        </tbody>
      </table>
    </div>;
};

<ComponentMetadata warehouses={["Snowflake", "Databricks", "Amazon Redshift", "Google BigQuery"]} componentType="Transformation" connectionInputs="Two" connectionOutputs="Unlimited" />

The **Detect Changes** transformation component lets you identify the differences between two datasets. Use this component to compare two separate tables that contain similar data, and then insert a new column that indicates whether the data in each row has been inserted, deleted, changed, or left unchanged.

Any rows with key columns that contain NULL values will be ignored. NULL comparison values are considered equal.

### Use case

This component can be used to keep your data up-to-date efficiently, without needing to reload all your data repeatedly. For example, you can use it to:

* Track changes to financial or healthcare data for compliance reasons.
* Identify rows that have been changed, making it easier to see only the most recent updates.

***

## Properties

<ResponseField name="Name" type="string" required>
  A human-readable name for the component.
</ResponseField>

{/* <!-- param-start:[masterTable] | warehouses: [snowflake, databricks, redshift, bigquery] --> */}

<ResponseField name="Master Table" type="drop-down" required>
  Select a master table from the two inputs. This table is the one treated as default in the comparison with the second table.
</ResponseField>

{/* <!-- param-start:[matchKeys] | warehouses: [snowflake, databricks, redshift, bigquery] --> */}

<ResponseField name="Match Keys" type="dual listbox" required>
  Select the key columns to join the two tables on. These columns must appear in both tables. NULL values are ignored.
</ResponseField>

{/* <!-- param-start:[compareColumns] | warehouses: [snowflake, databricks, redshift, bigquery] --> */}

<ResponseField name="Compare Columns" type="dual listbox" required>
  Select the columns that will be checked for changes. Just like the keys, these columns must appear in both tables; however, the two lists shouldn't overlap.
</ResponseField>

{/* <!-- param-start:[outputColumnMapping] | warehouses: [snowflake, databricks, redshift, bigquery] --> */}

<ResponseField name="Output Column Mapping" type="column editor">
  * **Input Column:** Select input columns to map to output names. Defaults are provided automatically but can be changed.
  * **Output Column:** Name each output column that the input columns will map to.

  Click the **Add all** button to automatically populate the **Input Column** and **Output Column** with all the columns selected in the **Compare Columns** property. You can then selectively edit the list if required, but if you click **Add all** again it will return the list to the default fully populated state, removing any changes you have made.
</ResponseField>

{/* <!-- param-start:[indicatorColumn] | warehouses: [snowflake, databricks, redshift, bigquery] --> */}

<ResponseField name="Indicator Column" type="string" required>
  Enter a name for the new column in the output. By default, this column is named "Indicator". This column contains an indicator that shows the status of each record:

  * **C** the record has been changed.
  * **D** the record has been deleted.
  * **I** the record is identical.
  * **N** the record is new.

  Switching the master table in the **Master Table** property will reverse the meaning of new (N) and deleted (D).
</ResponseField>

## Indicators

Indicators are single-letter codes that indicate what the state of a row is regarding Detect Changes. The following indicators are used:

* **C** Changed: the record is present in both tables, with different values, but with the same ID.
* **D** Deleted: the record is present in the master table, but not in the second table.
* **I** Identical: the same record is present in both tables with no changes.
* **N** New: the record isn't present in the master table, but is present in the second table.
