Tableau Migration Custom SQL Power BI

Tableau Custom SQL to Power BI: Native Queries, Query Folding, and What to Rewrite

July 28, 2026

Tableau runs custom SQL as a subquery: it has to wrap your statement in a SELECT of its own, because it cannot inject WHERE and GROUP BY clauses into SQL you wrote. Power BI does the same thing with a native database query, entered in the SQL statement box under Advanced options on the connector. The difference that matters is what happens to everything you do afterwards: in Power BI, how you paste the SQL decides whether later steps run on the database or on your own machine.

Custom SQL to Power Query conversion table

TableauPower BI equivalentNotes
Custom SQL queryNative database query in the SQL statement boxSimplest route, but subsequent steps stop folding
Custom SQL plus later filteringValue.NativeQuery(Source, "…", null, [EnableFolding = true])Keeps folding alive on supported connectors
Parameter inside custom SQLPower Query parameterBoth replace literal values only
Parameter driven by a user controlDynamic M query parameter bound to a fieldDirectQuery sources only
Initial SQLNo equivalentMove the logic into the query, a view, or the source
Joins on top of custom SQLModel relationships, or a database viewUsually a sign the SQL should become a view
Live connection on custom SQLDirectQuery with a native queryAll partitions must query a single source
Extract on custom SQLImport modeThe query runs at refresh, not at view time

Why the SQL statement box quietly costs you performance

Query folding is the mechanism that translates your Power Query steps into the data source's own language and pushes them down to it. Folding is full, partial or absent, and the difference is not cosmetic: without it, Power BI retrieves the raw result and filters, groups and sorts it locally.

A native query pasted into the SQL statement box returns a table, but Microsoft's own documentation is explicit that this route means your query "doesn't take advantage of any query folding from subsequent query steps". The documented alternative is to connect at the database level, then call Value.NativeQuery with EnableFolding = true. Power Query then wraps your SQL as a subquery and folds later steps into it, which is the same shape Tableau uses, except that here you can watch it happen in the query plan.

That option is connector-specific. It is documented for Amazon Redshift, Dataverse with enhanced compute, Google BigQuery, PostgreSQL, SAP HANA, Snowflake and SQL Server. Anywhere else, assume the pasted statement is the end of folding, and put the filtering inside the SQL itself. Folding also decides whether incremental refresh is worth configuring at all, since a policy whose filter does not fold pulls the whole table anyway.

Not all custom SQL should survive the migration

Tableau's documentation states plainly that using custom SQL can affect workbook performance, and a workbook estate full of it usually means the modelling was done in SQL because the data source could not express it. Power BI moves that work somewhere else, so the migration is a good moment to sort custom SQL into three buckets.

What the SQL doesWhere it belongs in Power BI
Window functions, complex joins, security predicatesStays SQL, ideally as a database view
Renaming, type casting, filtering, pivotingPower Query steps that fold
Denormalising several tables into one wide resultModel tables plus relationships
Unions of near-identical tablesPower Query append, or a view

A view is the underrated option. It moves the statement to where the DBA can see and index it, gives every report the same definition, and leaves Power Query with a plain table to fold against. It also removes the duplicate-column trap Tableau warns about, where the same field name arriving from two joined tables makes the field unusable.

Custom SQL under DirectQuery

When the Tableau workbook was live rather than extracted, the equivalent is DirectQuery over the same statement. Two things then change. All partitions of the model have to query a single source, so a native query that quietly reached across databases needs restructuring first. And report users can no longer be given free-form parameters: the supported route is a dynamic M query parameter, where a field in a table is bound to an M parameter so a slicer selection reaches the source query.

Treat that binding carefully. Microsoft documents an injection risk when parameter values are concatenated into query text, and recommends consuming them through operations that fold, a stored procedure, or the source language's own parameter mechanism instead. A Tableau parameter dropped into custom SQL carries the same exposure; it is simply less visible there.

What Antares does with custom SQL

The Analyzer records which data sources are backed by custom SQL rather than tables, and what each one connects to. That matters for scoping because those data sources are not a mechanical conversion: each is a modelling decision about whether the statement becomes a view, a set of folded Power Query steps, or a relationship in the model.

Conversion itself covers the dashboard layer. The rule the product follows is the same one that applies here: where a mapping is ambiguous, it is flagged rather than guessed, because a silently rewritten query is far more expensive to find in testing than a flagged one is to review. Run the free Analyzer to see where custom SQL sits in your own estate.

Related reading: data sources to Power BI datasets and calculated fields to DAX. Primary sources: Tableau's custom SQL documentation and Microsoft's guides to native database queries and the Value.NativeQuery function.

← Back to Complete Migration Guide

Related Migration Resources

Frequently asked questions

What is the Power BI equivalent of Tableau custom SQL?

A native database query, entered in the SQL statement box under Advanced options on the connector. Power Query runs it much as Tableau does, wrapping it as a subquery. For anything that needs later filtering to reach the database, use Value.NativeQuery with EnableFolding set to true instead.

Does custom SQL stop query folding in Power BI?

Through the SQL statement box, yes: Microsoft documents that subsequent query steps do not fold. Value.NativeQuery with EnableFolding = true keeps folding for later steps, and is documented for Amazon Redshift, Dataverse with enhanced compute, Google BigQuery, PostgreSQL, SAP HANA, Snowflake and SQL Server.

Can Tableau parameters inside custom SQL be converted?

Yes. A Power Query parameter covers the same ground, since both replace literal values only. To let a report user drive the value, bind a field to a dynamic M query parameter, which works for DirectQuery sources. Avoid concatenating user values into query text, which Microsoft flags as an injection risk.

Should custom SQL be kept or rebuilt during migration?

Keep SQL for what the database does best, such as window functions, complex joins and security predicates, ideally as a view. Move renaming, casting, filtering and pivoting into Power Query steps that fold, and turn denormalising statements into model tables with relationships.

Let's talk migration.

Get your free Migration Readiness Score, or talk to our team about end-to-end delivery.