SQL Editor
Ask anything of your data in SQL, save queries as reusable tables, and chart them on dashboards.
When a question doesn't fit a trend, funnel or retention chart, write SQL. SQL Editor in the sidebar has everything you can query on the left, the editor on top and the result below.
SELECT person.properties.plan AS plan,
uniq(person_id) AS weekly_users
FROM events
WHERE timestamp > now() - INTERVAL 7 DAY
GROUP BY plan
ORDER BY weekly_users DESCPress ⌘ ↵ (Ctrl ↵ on Windows and Linux) to run it.
The explorer
The panel on the left lists everything you can query:
- Tables, with row counts. Open one to see its columns and their types.
eventsalso lists every property asproperties.<key>(with how many events carry it) and its event names;personslists person properties, andgroupslists each group type's properties. - Views: your saved queries, which work as tables.
- Computed properties: person properties that saved queries write.
- Cohorts, with their size.
Double-click a name, press ↵, or drag it into the editor to insert it. Hover a row for its description, and use ▶ Preview to see its first 100 rows or most common values. Preview runs in the editor when it's empty, and in a new tab otherwise, so you don't lose your work. Right-click a row for everything else: copy its name, insert a cohort as inCohort(person_id, 3), or open, rename or delete a view.
Search finds tables, columns, properties, views and cohorts. The filter button hides built-in $ properties, system tables or empty sections. Use the arrow keys to move through the list. Drag the panel's edge to resize it, or collapse it with ‹.
Tables
| Table | One row per |
|---|---|
events | Event your apps sent |
persons | Person |
sessions | Visit: start and end, duration, pageviews, entry and exit page, source, bounce |
groups | Company, team or other group |
person_overrides | Merged identity: an old person id and the person it now belongs to |
cohort_static_members | Member of a static or SQL cohort (use inCohort() for any cohort) |
Times are in your project's timezone. person_id already joins up the ids of someone who used several devices before signing in, so uniq(person_id) counts real people.
Shorthands
| Write | To get |
|---|---|
properties.plan | A property, as text. Use properties['my key'] for keys with spaces. |
toFloat64OrNull(properties.amount) | A property as a number |
person.properties.email | On events: the property of the person who sent the event |
inCohort(person_id, 3) | Whether the person is in cohort 3 |
The editor completes tables, views, columns, property keys and cohorts as you type. After properties. it suggests the keys of the table you select from.
Saved queries are tables
Save a query and give it a name like paying_users. From then on it works as a table in any other query:
SELECT count() FROM paying_users
WHERE upgraded_at > now() - INTERVAL 14 DAYThat's how you build your own definitions, like "active account", "first order" or "power user", once, without setting anything up elsewhere. Saved queries can build on each other. Datahop checks a query runs before saving it, and won't delete one that another saved query or a cohort still reads from.
Charts and dashboards
Results show as a table, or switch to Line, Bar or Number and pick the columns to plot. Saving keeps the chart. ⋯ → Create alert watches one of its numbers (see Alerts). ⋯ → Add to dashboard puts it on any dashboard, including public ones: people with the link see the result, never the SQL. A dashboard's date range doesn't apply to SQL cards, because the query sets its own.
Copy or download any result as CSV from the result bar.
Cohorts and person properties from SQL
A saved query with a person_id column can feed the rest of Datahop. Open it and choose ⋯ → Use with people:
- Create cohort makes a cohort of everyone the query returns.
- Set person properties writes every other column onto those people. With the query below, each customer gets
ordersandlifetime_value, which you can then use to target a feature flag, segment an experiment or break down a chart.
SELECT person_id,
count() AS orders,
round(sum(toFloat64OrNull(properties.amount)), 2) AS lifetime_value
FROM events
WHERE event = 'order_completed'
GROUP BY person_idBoth recalculate every hour and whenever you change the query. People who drop out of the result lose the cohort membership or the properties. Datahop manages these property names, so don't also set them from your app. Turning Set person properties off removes them.
Ask AI
Ask AI turns a question into SQL that runs against your real events and properties, and explains what it returns. When a query fails, Fix with AI rewrites it using the error. Both need the AI assistant switched on for your workspace.
Agents
Agents use the same SQL. Over MCP, sql_schema lists the tables, saved queries, events, properties and cohorts; sql runs a query; and save_query saves one as a table, so an agent can define active_accounts once and every person and agent can use it. See the tool reference.
Hand this to your agent to connect it, then ask it questions in plain language. It writes and saves the SQL.
Limits
One read-only SELECT per run, up to 20 seconds and 10,000 rows. Aggregate in SQL or add a LIMIT for bigger results.