Toolarity

Grafana Join by Field Drops a Query? 4 Traps I Tested

Fix Grafana Published October 21, 2026

Two queries, one table: that’s what the Join by field transformation is for. You pick a field, Grafana puts rows with the same value side by side. When it works, it takes ten seconds. When it doesn’t, it usually fails without any message, and you end up with a table that is missing a query, missing rows, or showing numbers that belong to a different row.

I ran Grafana 13.2.2 (the current release, published 2026-09-15) in Docker and built 13 table panels from the built-in TestData data source (CSV content), so I could see exactly which rows go in and which come out. Query A is a list of disks, query B is their status:

Query A:

device_idmodel
d0Samsung 860 EVO
d1Kingston NV2
d2WD Blue

Query B:

namestatus
d0OK
d1Error
d3OK

Note that B calls its key column name, not device_id. That’s the first trap.

Short answer (Grafana 13.2.2, tested 2026-09-25):

What you seeLikely causeFix
The joined table only has columns from one queryThe key column has a different name in the other query. That query is dropped, with no warningRename the key first (Organize fields by name → rename), then Join by field
Rows that exist in only one query are goneMode is InnerUse Outer (tabular)
A key that appears twice shows up only onceMode is Outer (time series), the defaultUse Outer (tabular)
Numbers repeated across rows, columns named “currency 1” and “currency 2”You need two key columns, but Join by field takes oneUse Merge series/tables instead
The panel says “No data” after adding the joinNo field selected, and your data has no time columnPick the key in Field

The three modes, and which one to pick

The Mode dropdown has three options. Their descriptions in the Grafana source (tag v13.2.2, JoinByFieldTransformerEditor.tsx) are short, so here is what they did with my data. For this test B’s key was also called device_id:

Grafana 13.2.2, two tables joining query A and B on device_id. Inner shows only d0 and d1. Outer (tabular) shows d0, d1, d2 with an empty status, and d3 with an empty model.

  • Inner kept only d0 and d1, the keys that exist in both queries. d2 (no status) and d3 (no model) were dropped.
  • Outer (tabular) kept all four keys, with empty cells where a query had nothing (right).
  • Outer (time series) gave exactly the same four rows here (not pictured). With unique keys, the two outer modes behaved the same.

The Grafana docs (read 2026-09-25) describe the two outer modes as “for Time Series data” and “for SQL-like data”. The option descriptions in the source (JoinByFieldTransformerEditor.tsx, tag v13.2.2) are more specific: Outer (time series) is “Join on distinct field values”, Outer (tabular) is “Join on a field value with duplicated values”. That difference matters, see Trap 2.

Outer (time series) is the default. If you add the transformation and only pick a field, that’s the mode you get.

Trap 1: the key column has a different name

This is the most common version of the question on the Grafana forum (11,445 views when I read it): two queries return the same values, but in columns with different names. Join by field asks for one field name, so I picked device_id:

Grafana 13.2.2. Left: Join by field on device_id when query B calls its key "name". The table has only device_id and model, rows d0, d1, d2. Right: the same queries with the key renamed first. The table has device_id, model and status, rows d0 to d3.

On the left, query B is simply gone. No status column, no d3 row. The editor doesn’t show a warning either:

Grafana 13.2.2 edit view of the left panel. The Transformations tab has one Join by field step with Mode Outer (tabular) and Field device_id, no warning, and the preview table shows only device_id and model.

If you don’t look closely, this looks like a join that worked and found no matches.

Fix: rename the key in the second query before the join. I added Organize fields by name as the first transformation and renamed name to device_id, then Join by field on device_id. That produced the right table (right panel above).

Grafana 13.2.2 edit view with two transformations: 1, Organize fields by name, with a red message "Organize fields only works with a single frame. Consider applying a join transformation or filtering the input first."; 2, Join by field, Outer (tabular), device_id. The preview table still shows the correct joined result with d0 to d3 and a status column.

One thing that confused me: Grafana shows a red message on the Organize step, “Organize fields only works with a single frame”. The rename still worked in my test. The joined table has the status column and the d3 row, which it doesn’t have without the rename. I only tested renaming. I didn’t check whether reordering or hiding fields works in this position.

If your data source can rename in the query (for example label_replace in Prometheus, which is what the forum poster did, or AS in SQL), that avoids the extra step. I didn’t test those here.

Trap 2: duplicate keys and Outer (time series)

Now B has two rows for d0 (OK and Degraded), for example two status checks for the same disk:

Grafana 13.2.2, joining on device_id when query B has d0 twice. Left, Outer (tabular): d0 OK, d0 Degraded, d1 Error, d2. Right, Outer (time series): d0 Degraded, d1 Error, d2. The OK row is missing.

  • Outer (tabular) kept both d0 rows (left).
  • Inner also kept both d0 rows (not pictured: d0 OK, d0 Degraded, d1 Error).
  • Outer (time series), the default, kept only one d0 row, Degraded, which is the later row in query B. The OK row was dropped, without a message.

That’s what “distinct field values” means in practice. The mode is built for time series, where each timestamp appears once. For tables with repeated keys, use Outer (tabular).

Trap 3: two key columns

A Stack Overflow question (12,234 views) and a forum thread ask the same thing: the rows are identified by two columns, not one. Join by field only takes one field. I tested orders and refunds, both keyed by channel and currency:

Grafana 13.2.2, Join by field on channel: five rows, columns channel, currency 1, orders, currency 2, refunds. Web USD 10 orders appears twice, once with USD 1 refund and once with EUR 2 refunds.

Joining on channel alone matched every web row in query A with every web row in query B. Two web rows in each query became four, plus one for app. The second key column appears twice, as “currency 1” and “currency 2”, and web USD is shown with a refund count of 2 that belongs to web EUR. Nothing in the table tells you it’s wrong unless you compare the two currency columns.

Fix: use Merge series/tables instead of Join by field. That’s also the accepted answer on Stack Overflow. Merge matched rows where all shared columns (here channel and currency) had the same values, and gave the three correct rows. There’s nothing to configure.

Grafana 13.2.2, Merge series/tables on the same two queries: three rows, web USD 10 orders 1 refund, web EUR 4 orders 2 refunds, app USD 7 orders 0 refunds.

I didn’t test Merge with queries that share a text column that isn’t a key, for example a description that differs between the two queries.

Joining three queries

You don’t need one join per query. A single Join by field on device_id, Outer (tabular), combined three queries into one table:

Grafana 13.2.2, one table from three queries joined on device_id: d0 Samsung 860 EVO OK 35, d1 Kingston NV2 Error 41, d2 WD Blue with empty status and temperature, d3 with only status OK.

Every query needs the key under the same name, see Trap 1. A GitHub issue titled “No way to join the results from 3 queries into single Dataframe” is closed. I only tested this with CSV data from TestData.

Trap 4: “No data” after adding the join

When I added Join by field and didn’t select a field, the panel showed No data. In the v13.2.2 source (joinByField.ts), the default options are no field and the Outer (time series) mode. The docs say the join then uses “the first time column”. My test data had no time column, so there was nothing to join on. Pick your key in Field and it works.

What I’d do

  • Check that the key column has the same name in every query before you add the join. If one query seems to vanish, that’s the first thing to look at.
  • Use Outer (tabular) for table data, not the default Outer (time series). It keeps unmatched rows and doesn’t drop repeated keys.
  • If rows are identified by more than one column, use Merge, not Join by field.
  • After any join, count the rows and compare them with the raw queries (Table view in the panel editor). None of the problems above shows a warning.

What this test does not cover

  • Only Grafana OSS 13.2.2 in Docker, tested 2026-09-25, with the TestData data source (CSV content). I didn’t test Prometheus, SQL or the Infinity plugin, so I can’t say how their field names and types behave in a join.
  • Time series data joined on the time column, and joins where the key has different types (number in one query, text in the other).
  • Grafana Cloud and older self-hosted versions.