cancel
Showing results for 
Search instead for 
Did you mean: 
Data Engineering
Join discussions on data engineering best practices, architectures, and optimization strategies within the Databricks Community. Exchange insights and solutions with fellow data engineers.
cancel
Showing results for 
Search instead for 
Did you mean: 

CSV export from AI/BI Dashboard table widget does not preserve visual column order

Pavel_Sinkevich
New Contributor III

Summary

When downloading data as CSV from a table widget on an AI/BI Dashboard (kebab menu → Download → Data → Download CSV), the column order in the exported file does not match the column order displayed in the dashboard. All aggregated (measure) columns are placed before dimension columns, regardless of how columns are arranged in the widget configuration.

Steps to reproduce

  1. Create an AI/BI Dashboard with a table widget containing both dimension and measure columns
  2. Arrange columns in the widget so that dimensions appear before measures (e.g., product_name, product_type, …, SUM(available_stock), sum(reserved_stock))
  3. Click the kebab menu (⋮) on the widget → Download → Data → Download CSV
  4. Open the downloaded CSV file and inspect the column headers

Expected behavior

The CSV column order matches the column order configured in the table widget on the dashboard canvas.

Actual behavior

Aggregated columns (sum(...)) are moved to the beginning of the CSV, before all dimension columns. For example:

sum(available_stock), sum(reserved_stock), product_name, product_type, ...

Instead of the dashboard order:

product_name, product_type, ..., sum(available_stock), sum(reserved_stock)

Impact

Users who rely on CSV exports for downstream processing or reporting receive columns in an unexpected order, requiring manual reordering every time. This is particularly disruptive when exports are shared with non-technical stakeholders who expect the CSV to mirror the dashboard layout.

Environment

Databricks AI/BI Dashboards (Lakeview)

6 REPLIES 6

tom_n
Databricks Employee
Databricks Employee

I had a go at reproducing this on a current AI/BI build and couldn't get a plain table widget to misbehave. I built a table grouping dimensions plus sum(...) measures, arranged dimensions-first, and the exported CSV kept that order every time.

I tested three ways: a small result (client-side export), a result over 64,000 rows (which forces the server-side export path), and a case where the widget's query listed the measures first while the display showed dimensions first. In all three the CSV column order matched the screen.

So the trigger looks specific to your setup rather than table exports in general. A few questions to narrow it down:

1. Is the widget a plain Table, or a Pivot table (or a table exported with the pivot option)? Pivot exports use a different serialisation path, and there's a known issue there with columns not lining up in the exported file that's being worked on.
2. How many rows does the table return, and does the download arrive instantly or after a short "preparing" delay? 
3. Did you drag columns to reorder them in the dashboard view before exporting? A reorder in the viewer isn't always saved back to the widget, so the export can fall back to the original order.
4. Any calculated fields, renamed columns, or conditional formatting on the table?
5. Which cloud, region, and browser? Export behaviour has shifted across builds, so this helps work out whether it's already been fixed.

Hello,

1. Is the widget a plain Table, or a Pivot table?

The widget type is Table. When I export the dashboard into a json file, the relevant part looks like this:

{
    "widget": {
        "name": "stock-position",
        "queries": [
            {
                "name": "main_query",
                "query": ...
            }
        ],
        "spec": {
            "frame": ...
            "version": 2,
            "widgetType": "table",
            "encodings": {
                "columns": [
                    {
                        "fieldName": "inventory__warehouse"
                    },
...
                    {
                        "fieldName": "sum(inventory__in_stock_quantity)",
                        "displayName": "in_stock_quantity"
                    },
                    {
                        "fieldName": "daily(inventory__best_before_date)"
                    },
...
                ]
            },
            "data": {
                "queryName": "main_query"
            }
        }
    }
}

And when I click kebab menu (⋮) → View visualization query, the query for this table looks like this:

WITH `inventory` AS (

# exact copy of the query of dataset "inventory"

)
SELECT
SUM(`inventory`.`in_stock_quantity`) `sum(inventory__in_stock_quantity)`,
...
`inventory`.`warehouse` `inventory__warehouse`,
DATE_TRUNC('DAY', `inventory`.`best_before_date`) `daily(inventory__best_before_date)`,
...
FROM
`inventory`
GROUP BY
`daily(inventory__best_before_date)`,
...
`inventory__warehouse`

As you can see, in the visualization query the aggregated columns are listed first, even though they don't go first in the widget definition.

2. How many rows does the table return

Around 170.000

3. Did you drag columns to reorder them in the dashboard view before exporting?

Yes

4. Any calculated fields, renamed columns, or conditional formatting on the table?

There are several aggregated columns (using SUM), and datetime columns are converted to date using DATE_TRUNC.

Aggregated columns have custom Display name set in the widget. But I noticed that custom Display name is not showing up in Visualization query.

5. Which cloud, region, and browser?

Azure, West Europe. The same issue reproduced in Google Chrome and Microsoft Edge.

tom_n
Databricks Employee
Databricks Employee

I built a copy of your setup on a current workspace and couldn't get it to fail, which is itself a useful clue.

I matched it fairly closely: a plain table, several SUM measures with custom display names, a date column via DATE_TRUNC, columns dragged so the display shows dimensions first, and around 170,000 rows so the download goes through the large server-side export rather than the in-browser one. The generated visualisation query listed the aggregates first, same as yours. The exported CSV still came out in the display order, dimensions first, not aggregates first. I only moved a column using the UI and that still came out in the correct order.

NB: the custom Display name is not showing up in Visualization query - this is the same for me.

So on a current build the export lines up with the on-screen order even in your exact shape. That points to this being specific to your build or region rather than table exports in general, and it may already be fixed on a newer build.

A few things that would help pin it down:

1. Run the same export but filtered to well under ~64,000 rows, everything else identical. Does the smaller file come out in the right order (dimensions first), or still aggregates first? And does the small one download instantly while the 170k one shows a "preparing" step? That tells us whether it's tied to the large export path specifically.
2. Does the same reordering happen in Excel and TSV, or only CSV?
3. If you set the column order in the query itself so the dimensions come first, rather than only dragging them in the view, does the export then line up? That also works as a stopgap if it does.

Akash_Murade
New Contributor II

We are having the same problem.

I suspect this could be due to creating a relationship between datasets.

Steps to reproduce:

1. Create a dashboard with 2 Datasets:

-- Measures
SELECT
  id,
  CAST(MOD(id * 7 + 13, 1000) AS DECIMAL(10, 2)) AS qty1,
  CAST(MOD(id * 11 + 7, 500) AS DECIMAL(10, 2)) AS qty2,
  CAST(MOD(id * 3 + 17, 250) AS DECIMAL(10, 2)) AS qty3
FROM
  RANGE(200000) t(id)
-- Dimensions
SELECT
  id,
  CONCAT('D', MOD(id, 10)) AS dim01,
  CONCAT('D', MOD(id, 20)) AS dim02,
  CONCAT('D', MOD(id, 30)) AS dim03,
  CONCAT('D', MOD(id, 5)) AS dim04,
  DATE_ADD('2024-01-01', CAST(MOD(id, 365) AS INT)) AS order_date
FROM
  RANGE(200000) t(id)

2. Add relationship between datasets: 

Dimensions.id = Measures.id
-- One to Many

 3. Add table widget:

id, dim01, dim02, dim03, dim04, order_date, SUM(qty1), SUM(qty2), SUM(qty3)

4. Export the widget as Excel, CSV and TSV. Compare header and data order in each.

Results Found:

  • CSV / TSV: Aggregate columns are moved to the front for both header and data.
  • Excel: The header row stays in widget's configured order. But the data order is still aggregates first.

Note: The Excel issue occurs when the query executes against the warehouse during the export.

 

I agree that the relationship between datasets is a likely reason for the issue. I forgot to mention it, but we also have 2 datasets with many-to-one relationship: Orders and Inventory. The table widget is using dataset Inventory, but some of the filter widgets use fields from dataset Orders (such as Order Date).

Akash_Murade
New Contributor II

This issue occurs if your dashboard has a semantic model attached i.e., you've clicked "Get started with relationships" even if it doesn't have any relationships defined. Just having the semantic model present is enough to trigger it.

The problem is in how the query is generated when a semantic model exists. It puts aggregated columns first, then the other columns after, regardless of the column order configured in the widget.

Workaround: If you're seeing this problem but don't have any relationships set up, check whether a Relationship Graph (Semantic Model) is still attached to the dashboard, and remove it. This thread discusses removing the semantic model: How to remove/delete a Relationship Graph (Semantic Model) from an AI/BI Dashboard.

Hopefully this gets fixed soon.