Work with DAX query view

Use DAX query view in Power BI to view and work with Data Analysis Expressions (DAX) queries on semantic models.

DAX queries

In Power BI, DAX formulas define different types of calculations for your data and also set up role security. DAX queries return data from the model.

DAX queries are similar to SQL queries because they show you data you already have. DAX queries don't create items in the model or visuals in the report.

DAX queries have two main parts:

  • An EVALUATE statement, which is required. It specifies what data the query returns and how it's returned.
  • A DEFINE statement, which is optional. It lets you define DAX formulas, like a measure, to use in the query. Measures created or updated using the DAX query DEFINE MEASURE are DAX query scoped measures, running only in the context of the DAX query. You can add DAX query scoped measures to the model using CodeLens update model actions or the Update model with changes button.

Learn more about query syntax in DAX queries, or compare SQL and DAX examples in the SQL to DAX query cheat sheet in this article.

Open DAX query view

In Power BI Desktop, select the DAX Query View icon on the left side.

Screenshot of the DAX query view icon in Power BI Desktop.

In the Power BI service or Fabric portal workspace, select Write DAX queries from the context menu.

Screenshot of the Write DAX queries entry point in the context menu of a semantic model.

In the Power BI service or Fabric portal semantic model details page, select Write DAX queries at the top of the page.

Screenshot of the Write DAX queries entry point in the details page of semantic model.

DAX query view layout

Let's take a closer look at DAX query view in Power BI Desktop.

Diagram that shows the DAX query view layout.

DAX query view has these elements:

Ribbon

The DAX query view ribbon has common actions used when writing DAX queries.

Screenshot of the DAX query view ribbon.

Let's take a closer look at elements in the ribbon:

Format

Select the Format ribbon button or use SHIFT+ALT+F to format the current query. The query is indented with tabs. DAX functions are changed to UPPERCASE, and extra lines are added. Formatting your DAX query is considered to be a best practice and improves the DAX query readability. The formatting also indents in such a way that you can collapse and expand sections of the query.

Screenshot of the Format button.

Comment and uncomment

Select the Comment ribbon button to add a double forward slash (//) to the beginning of the line where the cursor is or all the selected lines. This action comments out the lines. When the DAX query is run, those lines are ignored.

Select the Uncomment ribbon button to remove // at the beginning of any line where the cursor is or all the selected lines. It doesn't work on lines where multiple line comment notation is added.

You can also use CTRL+/ to toggle between comment and uncomment.

Screenshot of the Comment and Uncomment buttons in the DAX query view ribbon.

Find and replace

Select the Find ribbon button or use CTRL+F to search for text in the DAX query editor. Find includes options to match case, match whole word, use a regular expression, and cycle through all matches for the current query. You can also select the chevron to the left of the Find box to enter Replace.

Screenshot of the find button in the DAX query view ribbon.

Select the Replace button in the ribbon or use CTRL+H to search for and replace text in the DAX query editor. Replace includes options to preserve the case and replace one at a time or all at once.

Screenshot of the Replace capability in the DAX query view ribbon.

Command palette

Select the Command palette ribbon button or use CTRL+ALT+P to open the command palette box. You can search for more DAX query editor actions and see their associated keyboard shortcuts.

Screenshot of the DAX query view command palette.

Command bar

The DAX query view command bar includes the most important actions when using DAX query view.

Run and cancel

The Run button executes the DAX query or the selected lines of a query. The status of a query after it runs appears in the lower status bar.

Screenshot of the DAX query view command bar.

When a query is running, the button becomes a Cancel button, which can be used to stop a running query.

Screenshot of the DAX query view cancel.

Update model with changes

The Update model with changes button adds or overwrites model measures with the DAX formulas from the DAX query scoped measures. DAX query scoped measures are DAX formulas in the DEFINE MEASURE block. Alternatively, you can choose to add or overwrite model measures individually using the CodeLens text that appears above each one.

DAX query editor

DAX query view includes a query editor where you can write and edit queries. It's more than just a bigger DAX formula bar. It's more powerful and has many similarities to the DAX editor available in Visual Studio Code.

DAX query editor has the following elements:

Suggestions and IntelliSense

Type in your query and get help with suggestions and IntelliSense while editing.

Screenshot of the DAX query editor intellisense.

Use ENTER or TAB to add the highlighted IntelliSense, or SHIFT+ENTER or ALT+ENTER to move to another line without adding the IntelliSense option. Selecting ESC closes any of the overlays.

Hover to see measure formulas

When a measure is included in the DAX query, you can hover on it to see the formula, name, and description.

Screenshot of the hover to see measure formula feature.

Select to see measure light bulb quick actions

Selecting on a measure in an EVALUATE statement in a query without a DEFINE statement shows the quick actions light bulb. Select Define or Define with references to create a DEFINE statement with this measure’s formula with or without the reference measure DAX formulas.

Update model measures using CodeLens

Using DEFINE MEASURE is helpful when creating measures by first allowing you to create them as DAX query scoped measures. You can edit multiple measures in one window, and then run the query to see the results of all or just some of them with specific group by columns. You don't need to create a table visual in Report view and switch back and forth between measure formulas. CodeLens takes this one step further by providing prompts when the measure already exists in the model. These offer quick links to add the measure or overwrite the measure in the model.

CodeLens is the clickable text that shows above a DEFINE MEASURE block. For DAX query scoped measures that aren't already present in the model, the Update model: Add new measure CodeLens appears, which adds the model measure when clicked. For DAX query scoped measures that are already present in the model, and when the DAX scoped measure DAX formula is different, the Update model: Overwrite measure CodeLens appears. This changes the model measure to this DAX formula when clicked.

Alternatively, you can add or overwrite multiple measures at once by clicking the Update model with changes button in the Command bar.

Screenshot of the Update model with changes button available in DAX query view.

Add measure descriptions

You can add measure descriptions directly in DAX query view using the triple-slash (///) comment syntax that TMDL supports for both measure and function descriptions. Add one or more /// comment lines directly above your MEASURE definition, select Update model with changes, and the description is saved to the model along with the measure definition.

DEFINE
    /// Year-over-year sales growth, as a percentage.
    /// Returns BLANK when there is no prior-year value.
    MEASURE Sales[YoY Growth %] = ...

Once saved, the description travels with the measure. Hover over the measure in DAX query view, in Model Explorer, or in the Data pane to see the description in the tooltip next to the measure name. The description also carries through to the quick queries that DAX query view generates. When you right-click a measure and choose Quick queries > Define and evaluate (or any other Define option), Power BI generates a DEFINE MEASURE statement in DAX query view that includes the description as /// comments above the measure definition.

Measure update workflow

The light bulb quick actions and CodeLens can be used together in a complete workflow:

  1. In the context menu of a measure, choose Quick queries, and then Evaluate to have the query created for you in a new Query tab.
  2. Select the measure in the query to Define or Define with references, adding the DEFINE statement.
  3. Make DAX formula updates to the measure, and then run the DAX query to see the results.
  4. When the change appears as expected, use the CodeLens Update model: Overwrite measure to save it back to the model.

Here's a more visual way to understand the workflow:

Diagram of the workflow.

Results grid

When a query is run, the results are shown in the Results grid.

Screenshot of the results grid.

If there's more than one EVALUATE statement in the query editor, then multiple results can be returned. You can use the Result dropdown to switch between them. The Copy button copies the entire grid as a tab delimited table with headers. Resize the grid by dragging the upper right hand corner arrows or the border between the result grid and the query editor.

Sort and filter results

The Results grid includes options to sort and filter the returned results. Use the column headers to sort the results, and apply filters to narrow down the rows shown. These options are helpful for validating that the results returned match what you expect from the DAX query, without writing and running additional queries.

Sorting and filtering apply only to the results that were already returned, which might be truncated. If the results are truncated, sorting or filtering in the grid doesn't reflect the full result set. To validate a truncated result, add the equivalent ORDER BY and filter logic to the DAX query itself, and then rerun the query.

Errors in the results grid

If the query results in an error, the results grid shows it.

Screenshot of the error message in the results grid.

A copy button transfers the error to your clipboard. The beginning of the error indicates where in the query the error is. In the image above the error is: Query (4, 23) The value for 'Sales 2' can't be determined. Either the column doesn't exist, or there is no current row for this column.

And "Query (4, 23)" indicates the error is on line 4 and at character 23.

Query tabs

DAX query view can have multiple query tabs, which can be renamed or removed. They also show the current state of the query.

Screenshot of the Query tabs.

Each tab includes a status indicator:

  • No indicator shows before running the query.
  • A green checkmark indicates a successful query run.
  • A red cross indicates an error occurred.
  • A filled square in a circle indicates the query was canceled.
  • A clock indicates the query is running.

Queries can run in the background allowing you to continue working on other query tabs.

Saving of DAX queries

DAX query view query tabs are saved in the file when you save from Power BI Desktop, so you can continue where you left off when you open the file again. If you use the developer mode to save a Power BI project, each query tab is included as a .dax file in the DAXQueries folder of the semantic model folder, or report folder if they're created in a live connected report. Learn more at the Power BI developer mode documentation.

Currently, you can't view or edit the DAX queries previously added in Power BI Desktop in the Power BI service. Viewers of the report or semantic model don't see the DAX queries saved with the semantic model.

DAX query view tabs are discarded on close when you Write DAX queries from the Power BI service or Fabric portal.

Data pane

The Data pane shows the items in the model to help you write queries. The editing paths for most of these items is blocked in the query view.

Quick queries

The Data pane context menu includes Quick queries. Use quick queries to create queries in a new query tab for tables, columns, and measures. Quick queries are designed to be a productivity boost for common tasks and built so they can easily be further modified. All quick queries are created in a new query tab and are run automatically.

Anywhere
  • Define all measures in the model creates a query with all the measure formulas shown in a query. Easily search all your measure formulas.

  • Define new measure creates a query with a define measure block. Use this to create your own measure in DAX query view then add to your model when you're ready.

Tables
  • Show top 100 rows creates a query by using SELECTCOLUMNS() to show the top 100 rows of the table. The columns are listed on each line to allow for easy modification by commenting out lines. An ORDER BY is also included to specify your sort order.

    Screenshot of the show top 100 rows.

  • Show column statistics creates a query showing statistical information for every column in your table. See many of the formulas for how to aggregate columns as MIN, MAX, AVERAGE, COUNT, and more.

  • Define all measures in this table creates a query with this table’s measure formulas shown in a query.

Columns
  • Show data preview creates a query using DISTINCT() to see the values of a column.

    Screenshot of the show data preview.

  • Show column statistics creates a query showing statistical information for this specific column. See many formulas for how to aggregate the column as MIN, MAX, AVERAGE, COUNT, and more. The query returned varies depending on the data type of the column, showing different statistics for numeric, text, and date columns.

    Screenshot of the show column preview.

Measures
  • Evaluate creates a query to show the result of the measure. SUMMARIZECOLUMNS() is used so you can add in any group by columns to show the measure by specific groups such as Country, Product, etc.

    Screenshot of evaluate measure.

  • Define and evaluate creates a query to show the result of the measure and show the measure’s formula in a DEFINE statement that can then be modified.

    Screenshot of the define and evaluate measure.

  • Define with references and evaluate creates a query to show the result of the measure and show not only the measure’s formula in a DEFINE statement that can be modified, but also any other measures referenced in the measure formula. Edit any part in the full context of the measure.

    Screenshot of define with references and evaluate.

Getting visual DAX queries from Performance Analyzer

Visuals in Report view get data from the model by creating a DAX query. You can view the visual query in DAX query view by using Performance Analyzer. Performance Analyzer gives you insight into why a visual might show an unexpected value, or lets you quickly start a query you can change.

In Report view, go to the Optimize ribbon, then select Performance Analyzer. Select Start recording, then Refresh visuals. In the following table, expand a visual to see options to copy the query or run it in DAX query view. Select Run in DAX query view to add the visual query as a new Query tab in DAX query view, and run it.

Screenshot of visual DAX queries in the Performance Analyzer feature.

DAX query view and live connect in Power BI Desktop

Power BI Desktop lets you live connect to a published Power BI semantic model by selecting Connect when you select a semantic model in the OneLake catalog. The lower right-hand corner of Report view shows Live connected to the Power BI semantic model. Use DAX query view to write DAX queries when live connected.

Model measures

When live connected to a published Power BI semantic model, you can't view or edit model measures. Quick queries options are limited to Evaluate.

Report measures

When live connected to a published Power BI semantic model, you can create report measures. Create report measures using the New measure action in Report and Model view. Report measures are only available in the current report. After you create a report measure, Quick queries in DAX query view shows the option to Define with references and evaluate. DAX queries run on the semantic model, so report measures must always be converted to DAX query scoped measures in the DEFINE MEASURE block to run, because they don't exist in the model itself.

The Update model with changes button and CodeLens options to Update model aren't available for report measures.

DAX query view in web

Use DAX query view in the web to write DAX queries from published semantic models. DAX query view in the web offers the same experience as Power BI Desktop, with a few exceptions.

  • User can edit data models in the Power BI service (preview) You need to enable the Power BI workspace setting to write DAX queries. Learn more at Edit data models in the Power BI service.
  • DAX queries are discarded on close. DAX queries in Power BI Desktop save to the model, and a semantic model can have DAX queries already saved in the model. DAX query view in the web doesn't display previously saved DAX queries in the semantic model, and queries you create in the web aren't kept after you close the browser.
  • Write DAX queries requires write permission on the semantic model. Workspace viewers need to use Power BI Desktop with a live connection to the semantic model to write DAX queries.

You can't add a DAX query as a parameter using ?query= after the URL to link to DAX query view in the web.

SQL to DAX query cheat sheet

If you're familiar with SQL, use the following examples to write DAX queries in DAX query view. SQL queries read database tables. DAX queries read tables in a semantic model, using table expressions after EVALUATE to specify the results.

These examples use a table named Sales with a unique SalesKey column and numeric ProductKey, Quantity, and SalesAmount columns. Use the following sample table, or replace the table and column names with names from your semantic model. The SQL examples use Transact-SQL syntax and assume the same data, with SalesAmount stored as a decimal column and the blank represented by SQL NULL.

Create the sample table

To try the DAX queries without connecting to a data source, create the sample table by using this Tabular Model Definition Language (TMDL) script. It uses Power Query to define 12 rows, including repeated product keys, tied sales amounts, and one blank amount.

Important

Use a new Power BI Desktop file for this sample. The createOrReplace command replaces any existing Sales table and its contents, including columns and measures.

  1. Open TMDL view in Power BI Desktop and paste the following script into a new script tab.
  2. Select Apply to create the table definition.
  3. On the Home ribbon, select Refresh to load the sample rows. Applying a TMDL script changes metadata but doesn't refresh the data.
  4. Open DAX query view, paste one of the DAX queries from this section into a query tab, and select Run.
createOrReplace

	table Sales

		column SalesKey
			dataType: int64
			summarizeBy: none
			sourceColumn: SalesKey

		column ProductKey
			dataType: int64
			summarizeBy: none
			sourceColumn: ProductKey

		column Quantity
			dataType: int64
			summarizeBy: sum
			sourceColumn: Quantity

		column SalesAmount
			dataType: decimal
			formatString: #,##0.00
			summarizeBy: sum
			sourceColumn: SalesAmount

		partition Sales = m
			mode: import
			source =
				#table(
					type table [SalesKey = Int64.Type, ProductKey = Int64.Type, Quantity = Int64.Type, SalesAmount = Currency.Type],
					{
						{1, 101, 1, 50},
						{2, 101, 2, 150},
						{3, 101, 10, 1000},
						{4, 102, 3, 300},
						{5, 102, 12, 1200},
						{6, 102, 1, null},
						{7, 103, 1, 100},
						{8, 103, 2, 200},
						{9, 103, 5, 500},
						{10, 104, 1, 50},
						{11, 104, 1, 50},
						{12, 104, 1, 50}
					}
				)

The row-count query returns 12, and the total-sales query returns 3,650. The missing-value query returns the row with SalesKey 6. The sample doesn't create a SQL database table.

Common query patterns

Each DAX query in the following table runs independently. For more information about query syntax, see DAX queries.

Task SQL query DAX query Learn more
Return all rows and columns. SELECT * FROM Sales EVALUATE 'Sales' EVALUATE
Select columns and assign an alias. SELECT ProductKey, SalesAmount AS Amount FROM Sales EVALUATE SELECTCOLUMNS('Sales', "ProductKey", 'Sales'[ProductKey], "Amount", 'Sales'[SalesAmount]) SELECTCOLUMNS
Filter rows. SELECT * FROM Sales WHERE SalesAmount > 100 EVALUATE FILTER('Sales', 'Sales'[SalesAmount] > 100) FILTER
Combine filter conditions. SELECT * FROM Sales WHERE Quantity >= 2 AND SalesAmount > 100 EVALUATE FILTER('Sales', 'Sales'[Quantity] >= 2 && 'Sales'[SalesAmount] > 100) DAX operators
Return distinct values. SELECT DISTINCT ProductKey FROM Sales EVALUATE DISTINCT('Sales'[ProductKey]) DISTINCT
Count rows. SELECT COUNT(*) AS SalesRows FROM Sales EVALUATE ROW("SalesRows", COALESCE(COUNTROWS('Sales'), 0)) COUNTROWS
Calculate a total. SELECT SUM(SalesAmount) AS TotalSales FROM Sales EVALUATE ROW("TotalSales", SUM('Sales'[SalesAmount])) ROW, SUM
Group and aggregate. SELECT ProductKey, SUM(SalesAmount) AS TotalSales FROM Sales GROUP BY ProductKey EVALUATE SUMMARIZECOLUMNS('Sales'[ProductKey], "TotalSales", SUM('Sales'[SalesAmount])) SUMMARIZECOLUMNS
Filter groups with HAVING. SELECT ProductKey, SUM(SalesAmount) AS TotalSales FROM Sales GROUP BY ProductKey HAVING SUM(SalesAmount) > 1000 EVALUATE FILTER(SUMMARIZECOLUMNS('Sales'[ProductKey], "TotalSales", SUM('Sales'[SalesAmount])), [TotalSales] > 1000) FILTER
Sort results. SELECT * FROM Sales ORDER BY SalesAmount DESC, SalesKey ASC EVALUATE 'Sales' ORDER BY 'Sales'[SalesAmount] DESC, 'Sales'[SalesKey] ASC ORDER BY
Return the top 10 rows in order. SELECT TOP (10) * FROM Sales ORDER BY SalesAmount DESC, SalesKey ASC EVALUATE TOPN(10, 'Sales', 'Sales'[SalesAmount], DESC, 'Sales'[SalesKey], ASC) ORDER BY 'Sales'[SalesAmount] DESC, 'Sales'[SalesKey] ASC TOPN
Test for missing values. SELECT * FROM Sales WHERE SalesAmount IS NULL EVALUATE FILTER('Sales', ISBLANK('Sales'[SalesAmount])) ISBLANK

Subqueries

DAX doesn't use a nested SELECT statement for subqueries. Instead, use scalar or table expressions, and store intermediate results with VAR. The following examples show three common patterns.

Scalar subquery

This SQL query returns sales rows with an amount above the average for the entire table:

SELECT *
FROM Sales
WHERE SalesAmount > (SELECT AVG(SalesAmount) FROM Sales);

In DAX, define a scalar variable before filtering the rows. The average is calculated once, outside the row-by-row evaluation in FILTER.

DEFINE
    VAR AverageSales = AVERAGE('Sales'[SalesAmount])
EVALUATE
    FILTER(
        'Sales',
        'Sales'[SalesAmount] > AverageSales
    )

IN subquery

This SQL query returns all sales rows for products that have at least one sales row with a quantity of 10 or more:

SELECT *
FROM Sales
WHERE ProductKey IN (
    SELECT ProductKey
    FROM Sales
    WHERE Quantity >= 10
);

In DAX, create a single-column table of matching product keys. Use the IN operator to test whether each sales row's product key is in that table.

DEFINE
    VAR MatchingProductKeys =
        DISTINCT(
            SELECTCOLUMNS(
                FILTER('Sales', 'Sales'[Quantity] >= 10),
                "ProductKey", 'Sales'[ProductKey]
            )
        )
EVALUATE
    FILTER(
        'Sales',
        'Sales'[ProductKey] IN MatchingProductKeys
    )

Derived table

This SQL query aggregates sales by product in a subquery, then filters the result:

SELECT ProductKey, TotalSales
FROM (
    SELECT ProductKey, SUM(SalesAmount) AS TotalSales
    FROM Sales
    GROUP BY ProductKey
) AS ProductTotals
WHERE TotalSales > 1000;

In DAX, store the grouped table in a variable, then pass it to FILTER. Reference the column added by SUMMARIZECOLUMNS as [TotalSales], not ProductTotals[TotalSales]. A table variable can't qualify a column reference.

DEFINE
    VAR ProductTotals =
        SUMMARIZECOLUMNS(
            'Sales'[ProductKey],
            "TotalSales", SUM('Sales'[SalesAmount])
        )
EVALUATE
    FILTER(
        ProductTotals,
        [TotalSales] > 1000
    )

Differences to consider

These patterns aren't a general-purpose SQL translator. Keep the following differences in mind:

  • You define relationships between tables in the semantic model, not in each DAX query. Unlike SQL queries that specify joins, DAX queries can use existing model relationships without redefining how the tables are related. DAX calculations use filter context, and filters propagate through active relationships according to their configured filter direction.
  • DAX blanks aren't identical to SQL NULL values. Use ISBLANK to test for blanks. For example, DAX comparisons with = can treat a blank as zero, while SQL comparisons with NULL return unknown. See DAX operators.
  • COUNTROWS returns a blank for an empty table. The row-count example uses COALESCE to return zero, like SQL COUNT(*).
  • SUMMARIZECOLUMNS excludes groups when all supplied aggregation expressions return blank. SQL GROUP BY can retain groups whose aggregates are all NULL.
  • TOPN can return more than the requested number of rows when the boundary values tie. The example includes the unique SalesKey as a tie-breaker. TOPN doesn't guarantee result order, so use ORDER BY to sort the returned rows.

For more query syntax details and examples, see DAX queries in the DAX reference.

Considerations and limitations

Considerations to keep in mind:

  • 500+ lines in DAX query editor has noticeable lag when typing.
  • Light bulb quick actions for measures only display when no DEFINE statement is in the query tab.
  • Command palette shows some commands that don't yet work.
  • Result grid doesn't show columns and measures with specified format, such as Currency, Whole number with thousands, etc.
  • Set up of the initial Git integration from the workspace doesn't include DAX queries saved in published semantic model. Learn more at Fabric Git integration.

Limitations to keep in mind:

  • Maximum of 15MB of data per query. Once 15MB is exceeded, the current row completes, but no more rows are written.

  • Maximum of 1,000,000 values per query. If you query for 20 columns, you can get back max 50,000 rows (1 million divided by 20).

  • Define all measures in this table or model is unavailable when there are more than 500 measures.

  • Running DAX queries in the web has other limitations:

    • Maximum of 99,999 rows are returned per query.
    • Write permission on the semantic model. Viewers with build permission can use Power BI Desktop to live connect and use DAX query view to run DAX queries.
    • Only available for nondefault semantic models. You can use Power BI Desktop to live connect to the default semantic model and use DAX query view to run DAX queries.

    Note

    By November 30, 2025, all Power BI default semantic models are disconnected from their item and become independent semantic models. You can retain them if you still use them for reports or dashboards or delete them safely if they are no longer needed. For more information, see Blog: Decoupling Default Semantic Models for Existing Items in Microsoft Fabric.