Skip to content

Results and charts ​

中文

The panel under the editor has three tabs: Results, Chart and Overview. To the right of the tabs sit the result's size (N rows · M columns) and the Export CSV and Export Parquet buttons.

The Results tab also shows what the editor's Explain and Profile buttons produce — see Explain and Profile output.

The results grid ​

The grid starts with a # row-number column, followed by the query result columns. Numeric columns are right-aligned. Initial widths are calculated from the headers and first 200 rows, counting Chinese or Japanese characters as two characters wide. Widths range from 80 to 360 pixels at the default interface size and scale proportionally at other sizes. Drag column borders to adjust the widths; the # column cannot be resized. When the columns are wider than the panel, a horizontal scrollbar stays in view under them.

Click the arrows in a column's header to sort the loaded rows by it: descending, then ascending, then back to the query's order. Number columns sort as numbers, everything else as text (which puts ISO dates and times in order), NULL sorts last, and rows with equal values keep the query's order. A filter keeps the sort, and the next result starts unsorted. The sort is client-side, like the filter: to sort more rows than were loaded, use ORDER BY.

Cell rendering ​

ValueShown as
NULLthe literal NULL, in a muted color
BLOB<blob N bytes>
GEOMETRY<geometry N bytes>
Float with an integer value3.0
Timestamp2026-09-17 04:21:09.5 — in UTC, not local time; the fraction has as many digits as the value (nine for TIMESTAMP_NS)
IntervalDuckDB notation, such as 1 day 02:00:00
List / struct / mappretty-printed

The UTC rendering is worth remembering if you are eyeballing timestamps rather than comparing them in SQL.

Filtering ​

The filter box does a case-insensitive substring match across all cells of the loaded rows. It is client-side: it never queries the database, and it only covers the rows that were loaded, not the true result size.

The filter applies when you press Enter or clear the box, not on every keystroke. While a filter is applied, the grid reports visible / total rows beside it.

Row limits ​

Results are truncated at whichever of these binds first:

  • 100,000 rows
  • 2,000,000 cells — so a 400-column result produces only about 5,000 rows

The cell budget exists because a row cap alone does not bound the work: a PIVOT over a high-cardinality column returns one column per distinct value, and formatting tens of millions of cells would look like a hang.

Truncation is reported in a banner that quotes the real number of rows that were loaded. There is no pagination and no "load more" — narrow the query instead.

Copying ​

Hovering a cell reveals a copy button that puts that cell's text on the clipboard. Right-click a cell for Copy cell, Copy row (tab-separated), or Copy column (one value per line, in the displayed order). Right-click a row number to copy its row. Copies follow the current filter and sort. Dashboard tables offer the same three copy actions. There is no range selection and no "copy as SQL"; for more than a row or a column, use Export.

Export ​

Export CSV and Export Parquet open a small dialog with a path field, pre-filled with ~/Desktop/export.csv or ~/Desktop/export.parquet.

Two things to know:

  • The export re-runs the SQL that produced the current rows, so the file holds the query's full result set — not the filtered view, and not the truncated grid.
  • There is no file picker and no overwrite prompt. Type a path, and it is written.

Charts ​

Until you pick columns, a chart is drawn from the rows already in the grid, in the order the query returned them, with no aggregation. The X, Y and Split menus have DuckDB group the whole result instead.

The chart picker above the chart starts at Auto, which chooses from the result's columns:

The result hasAuto draws
A latitude and a longitude columnA map
A temporal first column (date / timestamp)An area chart; x is column 0, one series per numeric column
Anything elseA bar chart; column 0 is the label, the first numeric column is the value

"Numeric column" includes the first column: if column 0 is a number — an hour, a year, an ID — it becomes the bar chart's value, not its label. Cast it to text (year::VARCHAR, or format('{:02d}:00', hour(ts))) to make it the label.

Bar, Line, Area and Scatter are a click away for any result; Pie for a result whose first column is not a time, and Map for one with coordinates. The pick is kept across runs; when a new result cannot draw it — a map without coordinates — the chart falls back to Auto's choice without forgetting yours.

Pick columns ​

The X, Y and Split menus above the chart choose what it draws. Y is the row count, or the sum, average, minimum or maximum of a number. DuckDB then groups the whole result rather than the loaded rows, and keeps the 200 largest categories (or the first 50,000 ordered values) and the 12 largest series. A notice says what was left out.

  • With a Split picked, Stacked and Heatmap join the chart picker, and Pie leaves it.
  • Histogram is offered when there's a number to bin. DuckDB bins the whole result.
  • Copy as .dash copies your pick as a query and a plot block that draw the same chart in a dashboard.

Without a pick, a chart of a cut-off result says Drawn from the first N rows the grid loaded, not the whole result. A cut-off time series is run again in the background and averaged over every row.

Chart types and limits ​

A pie draws the first numeric column's value per label, largest first. Zero, negative and missing values are not drawn as slices, and a notice counts them; past 8 slices, the 7 largest keep their slices and the rest fold into "other".

A map is picked by column names:

  • Latitude: lat, latitude, or any name containing them (geo_lat, start_lat) — 纬度 works too.
  • Longitude: lng, lon, long, longitude, likewise — 经度 works too.

Each row is a point on a Web Mercator projection fitted to the points, over a latitude/longitude grid labelled in degrees; a text column with only a few distinct values colours them. Hover a point for its row.

Under the points, an OpenStreetMap base map can be drawn: turn it on with View → Online base map (OpenStreetMap). It is off by default because loading tiles needs the network — the requests reveal roughly the area being viewed, never your rows. Tiles are cached for a week; offline, the map draws over the latitude/longitude grid alone.

Rows whose value cells are not numeric — NULL, for instance — are dropped before plotting.

Limits, all announced in a notice line under the chart title:

LimitBehaviour
12 seriesExtra numeric columns are dropped
1,500 pointsThe series is bucketed and averaged within each bucket
200 barsSurplus bars are truncated, not merged
8 pie slicesThe smallest fold into "other"
20,000 map pointsSurplus points are left out

The title always reports how many points were plotted, so check it before trusting the shape of a curve.

Column overview ​

The Overview tab describes every column of the current result at once: how full it is, how many values it takes, its range, and what its values look like.

The heading line reads Current result · N rows · M columns · took …. Then each column gets one line:

PartWhat it shows
Name and typeThe column name and its DuckDB type
NullsThe share of rows that are NULL, with a small bar; highlighted when above 0%
Distinct~N distinct — DuckDB's estimate of the number of distinct values
RangeMinimum – maximum, or the single value when they are equal
MedianFor numbers, dates and timestamps
DistributionA small chart, described below

The distribution depends on the column's type:

  • Numbers, dates and timestamps get a histogram of about 12 equal-width bars. A column with a single value lists that value instead.
  • Text and booleans list their 5 most common values, each with its share of rows; hover a value for its exact count. Past about 10,000 distinct values the values are estimated and listed under Common values (estimated), without shares.
  • Lists, structs, maps and unions get no chart.

How it works:

  • The overview runs the query again, whole, in two scans: SUMMARIZE for the statistics, then one SELECT for every column's distribution. So it covers the full result, not just the rows the grid kept under its row limits — and a slow query is slow again. A query that is not deterministic (random(), USING SAMPLE) is described as it came out on that second run.
  • It is computed when you open the tab, and again for each new result while the tab is open.
  • Only a query that can sit inside FROM ( … ) can be summarized: one that starts with SELECT, WITH, FROM, VALUES, TABLE, PIVOT or UNPIVOT (leading -- comments are skipped). Anything else — SHOW, DESCRIBE, PRAGMA, CALL, SUMMARIZE — gets Only the result of a query (SELECT, WITH, FROM…) can be summarized: the overview runs it again.

To summarize a whole table, view or registered file without writing a query, right-click it in the sidebar and choose Column overview. That puts FROM <name>; in the editor, runs it and opens this tab. See Right-click menu.

Explain and Profile output ​

The Explain and Profile buttons in the editor toolbar show their output on the Results tab, switching to it if another tab was open. Either one replaces the grid; run the query again to get its rows back.

Explain shows DuckDB's plan as plain monospace text under a EXPLAIN · took … line.

Profile shows the plan that actually ran as a tree, one line per operator, each indented under the operator it feeds:

  • a bar for the operator's share of the time all operators spent;
  • the operator's own time, its children's excluded;
  • its name, such as TABLE_SCAN, FILTER or HASH_GROUP_BY;
  • N rows — the rows it produced;
  • est. N — the optimizer's estimate of those rows, where the plan has one. It is highlighted when it is off by more than 10× either way (hover it for Estimate off by more than 10×): a miss that size is a common reason a join is slow;
  • below, what the operator worked with: filters, join keys, projections.

The heading line reads Profile · took … · operators …: the wall-clock time, then the sum of the operators' own times. The two differ, because operators of one pipeline run interleaved; the bars are shares of the second. Beside it, Hottest: NAME (time) names the operator that cost the most on its own, and that operator's line is drawn in red.

Released under the Apache-2.0 License.