---
title: "SQL-powered attributes"
canonical_url: "https://docs.getdx.com/sql-powered-attributes/"
md_url: "https://docs.getdx.com/sql-powered-attributes.md"
last_updated: "2026-11-05"
---

# SQL-powered attributes
SQL-powered attributes set a [custom user attribute](https://docs.getdx.com/custom-user-attributes/) from a SQL query on your Data Cloud data, so you can filter and break down reports by anything you can query, without maintaining a CSV or an API integration.

> **Note**: SQL-powered attributes require Data Cloud. Only Data Cloud admins can create, edit, or run them.

## How it works

Each run sets every user's value from the query result. Users the query doesn't return lose their value, and a failed run changes nothing. Values only come from the query, so CSV uploads, the API, and manual edits can't change them.

## Writing the query

Return a `user_id` column with each user's `dx_users.source_id` and a `value` column with their attribute value.

### Example: AI usage

Groups users by how many days they used an AI tool in the last 30 days.

```sql
SELECT
    dx_users.source_id AS user_id,
    CASE
        WHEN COUNT(DISTINCT ai.date) >= 12 THEN 'Power user'
        WHEN COUNT(DISTINCT ai.date) >= 4 THEN 'Regular'
        WHEN COUNT(DISTINCT ai.date) > 0 THEN 'Trying it'
        ELSE 'Not yet'
    END AS value
FROM dx_users
LEFT JOIN ai_tool_daily_metrics ai
    ON ai.dx_user_id = dx_users.id
    AND ai.is_active
    AND ai.date >= CURRENT_DATE - 30
WHERE dx_users.deleted_at IS NULL
GROUP BY dx_users.source_id
```

### Example: Merged pull requests

Groups users by how many pull requests they merged in the last 90 days.

```sql
SELECT
    dx_users.source_id AS user_id,
    CASE
        WHEN COUNT(pull_requests.id) >= 30 THEN 'High'
        WHEN COUNT(pull_requests.id) >= 10 THEN 'Medium'
        ELSE 'Low'
    END AS value
FROM dx_users
LEFT JOIN pull_requests
    ON pull_requests.dx_user_id = dx_users.id
    AND pull_requests.merged >= CURRENT_DATE - 90
    AND pull_requests.deleted IS NOT TRUE
WHERE dx_users.deleted_at IS NULL
GROUP BY dx_users.source_id
```

### Limits

- Read-only queries, one row per user, up to 250,000 rows.
- Up to 2,500 distinct values, each up to 255 characters.
- Runs time out after your account's Data Studio query timeout.
- Data Studio variables such as `$team_ids` aren't supported.

## Creating a SQL-powered attribute

1. Go to **Settings** -> **Attributes** and click **New**.
1. Enter a **Name** and select **SQL-powered**.
1. Write the query and click **Test** to preview which users get which values.
1. Optionally, set a **Run schedule**: daily, weekly, or monthly, in your account's time zone.
1. Click **Publish**. The query runs right away.

To run it again later, use **Run now** from the attribute's menu. To change the query or schedule, click the attribute's name. If a run fails, the **Attributes** list shows **Last run failed** with the error.

## FAQs



### Why did a user lose their value?

The latest run didn't return that user, or returned a blank `value` for them.

### Why does Test say a user isn't recognized?

`user_id` must be `dx_users.source_id`. Data Studio reports use `dx_users.id`, so change the user column in a query copied from a report.
---

## Sitemap

[Overview of all docs pages](/llms.txt)
