CoreHRx Jobs

Apply in one click, save jobs and take free mock tests.

Register free Log in
Hiring? Post jobs with CoreHRx
My account
user

View & update profile
Interview guide

Power BI Interview Questions and Answers: 60 Questions from Easy to Hard

This guide is for freshers in India preparing for data analyst and Power BI developer interviews, and for experienced analysts and BI developers moving into senior roles. It has 60 questions with answers in three levels: the basics of Power BI Desktop, the Service, Power Query and modelling; then the DAX, relationships, security and refresh questions asked of people with a few years of experience; and finally performance, internals and design questions for senior roles. Many answers include a DAX measure or a Power Query step with worked numbers. Read the question, answer it aloud, then compare, and take the mock test to check yourself against the clock.

What Power BI interviews cover

  • Power Query: connecting to sources, cleaning and shaping data, merging and appending, data types and query folding.
  • Data modelling: star schema, fact and dimension tables, relationships, cardinality, cross-filter direction and the date table.
  • DAX: calculated columns versus measures, row and filter context, CALCULATE and context transition, ALL and REMOVEFILTERS, iterators such as SUMX, and time intelligence.
  • Reports: choosing visuals, filters and slicers, drill down and drill through, bookmarks and field parameters.
  • The Service: workspaces and apps, row-level security, scheduled and incremental refresh, gateways and performance tuning.

How to prepare (freshers and experienced)

  • Freshers: build one complete report from a sample sales file. Clean it in Power Query, model it as a star schema, write 10 to 15 measures and publish it.
  • Practise explaining DAX aloud. Interviewers often ask what a measure returns in a given cell, so predict the number before you check it.
  • Experienced candidates: prepare two or three stories from real projects, such as a slow report you fixed, an RLS design or a refresh failure, with numbers before and after.
  • Learn the tools senior roles expect around Power BI: DAX Studio, Performance Analyzer, Tabular Editor, gateways and deployment.
  • Revise SQL and Excel as well; most BI roles in India test both alongside Power BI.

Common mistakes and interview-day tips

  • Do not answer CALCULATE questions with a memorised definition. Walk through which filters are added, removed or kept in the cell being asked about.
  • Avoid saying you load everything into one flat table; explain why a star schema keeps measures simple and the model small.
  • When asked about performance, say how you would measure first, with Performance Analyzer or DAX Studio, before changing anything.
  • Be clear about which features you have used in production and which you know only from study, such as incremental refresh or deployment pipelines.
  • In a take-home task, keep the model clean, name measures clearly and add a short note on assumptions; reviewers open the model, not just the visuals.

Power BI interview questions: Easy questions (freshers)

20 questions

1. What is the difference between Power BI Desktop and the Power BI Service?

Power BI Desktop is the free Windows application where you build: you connect to sources, clean data in Power Query, design the model and relationships, write DAX and lay out report pages. The Power BI Service is the cloud platform in the browser where you publish, share and run that work: workspaces, apps, dashboards, scheduled refresh, gateway connections and RLS role membership live there. A common mistake is treating the Service as a viewer only; you can also build reports there on a published semantic model.

2. What is the difference between a semantic model, a report and a dashboard?

The semantic model, called a dataset before 2023, holds the data, relationships and measures. A report is a multi-page, interactive view built on one semantic model, with slicers, filters and drill-through. A dashboard exists only in the Service: a single canvas of tiles pinned from one or more reports, used as a quick summary for managers, and clicking a tile opens the report it came from. So you can build reports in Desktop, but dashboards only after publishing, and a dashboard is not just another name for a report.

3. What is Power Query, and what are applied steps?

Power Query is the data preparation engine in Power BI: you connect to a source, then filter, rename, change types, merge and reshape the data before it loads into the model. Each action in the editor is recorded as an applied step, and the steps together form a query in the M language, like the one shown. On every refresh the same steps run again on the new data, so the cleaning is repeatable. Give steps clear names and delete experiments you do not need, because every step runs at each refresh.

Example
let
    Source = Csv.Document(
        File.Contents("C:\Data\sales.csv"),
        [Delimiter = ",", Encoding = 65001]
    ),
    Promoted = Table.PromoteHeaders(Source, [PromoteAllScalars = true]),
    Typed = Table.TransformColumnTypes(
        Promoted,
        {{"OrderDate", type date}, {"Amount", type number}}
    ),
    Filtered = Table.SelectRows(Typed, each [Amount] > 0)
in
    Filtered

4. Why do data types matter in Power Query, and how do you load dates written as DD/MM/YYYY correctly?

Data types decide what you can do with a column: a number stored as text cannot be summed, and a date stored as text gets no date hierarchy and breaks time intelligence. Set types on purpose rather than trusting automatic detection. Dates from Indian systems often arrive as 05/04/2025 meaning 5 April; read with an en-US locale it becomes 4 May, or an error when the day is above 12. Use Change Type with Locale, or pass the en-IN culture as shown, so the text is read day first.

Example
Typed = Table.TransformColumnTypes(
    Source,
    {{"InvoiceDate", type date}, {"Amount", type number}},
    "en-IN"
)

5. What is the difference between Merge Queries and Append Queries?

Merge is a join: it adds columns from another table by matching a key, like a lookup. For example, merge Sales with Products on ProductID to bring in Category, choosing the join kind: left outer keeps all sales rows, inner keeps only matches, and left anti finds sales with no product. Append is a union: it stacks rows of tables with the same columns, such as the monthly files from the Chennai, Pune and Kolkata branches. A common mistake is appending tables whose column names differ slightly, which creates extra columns full of nulls.

Example
Merged = Table.NestedJoin(
    Sales, {"ProductID"}, Products, {"ProductID"},
    "Product", JoinKind.LeftOuter
),
Expanded = Table.ExpandTableColumn(Merged, "Product", {"Category"}),

Combined = Table.Combine({Sales_Chennai, Sales_Pune, Sales_Kolkata})

6. What is a star schema, and why is it recommended for Power BI?

A star schema has fact tables in the centre, holding events and numbers such as sales lines with quantity, amount and keys, surrounded by dimension tables that describe them: Date, Product, Customer and Store. Each dimension has a one-to-many relationship to the fact. The Power BI engine and DAX are designed for this shape: filters flow cleanly from dimensions to facts, measures stay simple and the model compresses well. The usual beginner mistake is loading one wide flat table, which makes some measures hard and the model often larger.

7. What is a relationship in a Power BI model, and what does cardinality mean?

A relationship links a column in one table to a column in another so that filters can travel between them, for example Product[ProductID] to Sales[ProductID]. Cardinality describes how many rows match on each side. One-to-many is the normal case: each product appears once in Product and many times in Sales. One-to-one is rare and usually means the tables could be combined, and many-to-many is for special cases. If the key on the one side has duplicates, Power BI cannot create a one-to-many relationship, so check the key first.

8. What is the difference between a calculated column and a measure?

A calculated column is computed row by row when the data refreshes and is stored in the model, so it uses memory but can go on slicers, rows or axes. A measure is computed at query time for each cell of a visual, using the filters in force there, and is not stored. Use a column for something you slice by, such as a price band; use a measure for anything you aggregate, such as total sales or margin percent. A common mistake is adding a calculated column for every number and summing it, which bloats large fact tables.

Example
-- Calculated column on Sales: one value per row, stored
Line Amount = Sales[Quantity] * Sales[Unit Price]

-- Measure: computed for each cell of a visual
Total Sales = SUMX ( Sales, Sales[Quantity] * Sales[Unit Price] )

9. What are implicit and explicit measures, and which should you use?

An implicit measure is what you get when you drag a numeric column into a visual and Power BI applies its default summarization, such as Sum or Count. An explicit measure is one you write in DAX, such as Total Sales = SUM(Sales[Amount]). Explicit measures are better for real reports: you name and format them once, reuse them inside other measures, and they behave the same everywhere. Calculation groups also need them. Check the default summarization of ID columns too, or Power BI will happily add up customer numbers.

10. What is the difference between COUNT, COUNTROWS and DISTINCTCOUNT in DAX?

COUNTROWS counts the rows of a table, COUNT counts the non-blank values in one column, and DISTINCTCOUNT counts the different values in a column, treating a blank as one value. On the four rows shown, COUNTROWS gives 4, COUNT gives 3 because one OrderID is blank, and DISTINCTCOUNT gives 3: 101, 102 and the blank. DISTINCTCOUNTNOBLANK ignores blanks and gives 2 here. When each row is one order, COUNTROWS on the table is the clearest; when lines repeat an order number, as 102 does, use a distinct count.

Example
Orders
OrderID
101
102
102
(blank)

Rows      = COUNTROWS ( Orders )
Non Blank = COUNT ( Orders[OrderID] )
Distinct  = DISTINCTCOUNT ( Orders[OrderID] )

11. What is the difference between RELATED and RELATEDTABLE?

Both follow an existing relationship from inside a row context. RELATED goes from the many side to the one side and returns a single value, such as the category of the product on the current sales row. RELATEDTABLE goes the other way and returns the related rows, such as all sales of the current customer, which you then count or sum. Neither works without a relationship or outside a row context, so RELATED written directly in a measure gives an error unless an iterator such as SUMX provides the row.

Example
-- Calculated column on Sales (many side): one value
Category = RELATED ( Product[Category] )

-- Calculated column on Customer (one side): related rows
Order Count = COUNTROWS ( RELATEDTABLE ( Sales ) )

12. Why should you use DIVIDE instead of the / operator in DAX?

DIVIDE(numerator, denominator) returns BLANK, or an alternate result you pass as the third argument, when the denominator is zero or blank. The / operator does not protect you: a zero denominator gives Infinity, or NaN for zero divided by zero, and that shows up in cards and tables. So margin percent for a new store with no sales yet shows blank with DIVIDE instead of an ugly value. Use / when the denominator can never be zero, such as dividing by the constant 100000 to show lakhs, because it is slightly simpler.

Example
Margin % = DIVIDE ( [Total Profit], [Total Sales] )

Margin % or Zero = DIVIDE ( [Total Profit], [Total Sales], 0 )

Sales in Lakhs = [Total Sales] / 100000

13. Why does a Power BI model need a separate date table, and how do you create one?

Time intelligence functions such as TOTALYTD and SAMEPERIODLASTYEAR need a table with one row for every date, with no gaps, ideally covering complete years. A separate Date table also gives one place for Year, Month, Quarter and financial-year columns, shared by every fact table. Build it in Power Query or with DAX as shown, relate Date[Date] to the date column of each fact, and mark it as the date table. Set Month to sort by Month No, otherwise months sort alphabetically: Apr, Aug, Dec and so on.

Example
Date =
ADDCOLUMNS (
    CALENDAR ( DATE ( 2024, 4, 1 ), DATE ( 2026, 3, 31 ) ),
    "Year", YEAR ( [Date] ),
    "Month", FORMAT ( [Date], "MMM" ),
    "Month No", MONTH ( [Date] ),
    "FY", IF ( MONTH ( [Date] ) >= 4, YEAR ( [Date] ) + 1, YEAR ( [Date] ) )
)

14. What are the Import, DirectQuery and Live connection modes?

Import copies the data into the model, compressed in memory. It gives the fastest visuals and full Power Query and DAX support, but data is only as fresh as the last refresh. DirectQuery leaves data in the source and sends a query for each visual interaction, so it suits very large or near-real-time data, but it is slower, loads the source and has some modelling limits. Live connection points a report at an existing published semantic model or Analysis Services, so that report has no Power Query or model of its own. Most models should start with Import.

15. How do you choose the right visual for a question?

Pick the visual from the question the viewer is asking. Trend over time: a line or column chart by month. Comparing categories: a bar chart sorted by value. One headline number: a card or KPI visual. Exact figures to check: a table or matrix. Share of a whole with two or three parts: a donut or stacked bar, never a pie with fifteen slices. Location: a map, only if geography matters. Keep each page to a handful of visuals that answer one question, such as how the Mumbai and Delhi branches did this quarter.

16. What are visual-level, page-level and report-level filters, and how do slicers and interactions fit in?

In the Filters pane, visual-level filters affect one visual, page-level filters affect every visual on that page, and report-level filters affect all pages. Slicers are filters on the canvas for viewers to use, and Sync slicers can make one slicer apply across pages. By default, selecting a point in one visual cross-filters or cross-highlights the others; Edit interactions on the Format ribbon sets each pair to filter, highlight or none. A frequent surprise is a forgotten page-level filter that explains why a total looks too low.

17. What is the difference between drill down and drill through?

Drill down moves through a hierarchy inside the same visual: from Year to Quarter to Month, using the arrows in the visual header. Drill through jumps from one page to another page filtered to the item you right-clicked, for example from a summary of all branches to a detail page for the Hyderabad branch showing its customers and invoices. To set it up, you add the field to the Drill through area of the target page. Use drill down for exploring levels of one hierarchy and drill through for detail pages.

18. What are bookmarks in Power BI, and what are they used for?

A bookmark saves the current state of a report page: filters and slicer selections, sort order, drill level, and which visuals are visible in the Selection pane. You create them in the Bookmarks pane and attach them to buttons or images, so a click can switch between a chart view and a table view, reset all slicers, or step through a story in a review meeting. Viewers in the Service can also save personal bookmarks. Bookmarks do not refresh data or add calculations; they only restore a saved view of the page.

19. What is row-level security, and how do you set up a simple role?

Row-level security limits which rows a user can see in the same report. In Desktop you create a role under Manage roles and give it a DAX filter on a table, such as the South Team role shown, which keeps only South rows in Store; the filter then flows through relationships to Sales. After publishing, you add users or groups to the role in the semantic model's security settings in the Service. Test it with View as before sharing. RLS applies to workspace Viewers and app users, not to Admins, Members or Contributors.

Example
-- Role: South Team
-- Table filter on Store
[Region] = "South"

20. What happens when you publish a report, and how do you keep its data up to date?

Publishing from Desktop uploads the semantic model and the report to a workspace, with the data as of your last refresh. To keep it current, open the semantic model settings in the Service, enter the data source credentials and set a scheduled refresh with failure e-mails turned on. Cloud sources such as SharePoint Online or Azure SQL refresh directly, while on-premises sources, such as a SQL Server in the Pune office or a file on a local drive, need a gateway. A common mistake is pointing the report at an Excel file on your own laptop.

Ready to check yourself? Take the free Power BI mock test

Power BI interview questions: Medium questions (1-3 years)

20 questions

21. What is the difference between row context and filter context? Why does the first measure shown fail?

Filter context is the set of filters active where a measure is evaluated: the row and column of the visual, slicers, page filters and any changes made by CALCULATE, for example City = Bengaluru and Month = March 2025. Row context means there is a current row, which exists in calculated columns and inside iterators such as SUMX or FILTER. A measure has no row context of its own, so the first formula fails with the error that a single value for column Amount cannot be determined. Aggregate the column or iterate the table, as the second measure does.

Example
-- Fails: a measure has no current row
Big Sale = IF ( Sales[Amount] > 100000, "Big", "Normal" )

-- Works: iterate the table
Big Sale Count =
COUNTROWS ( FILTER ( Sales, Sales[Amount] > 100000 ) )

22. With a slicer set to Laptop and Region on rows, what do the three percent-of-total measures shown return for North?

ALL(Sales[Region]) removes only the Region filter, so the Laptop slicer still applies: the denominator is 400 + 300 = 700 and North shows 57.1 percent. ALL(Sales) removes every filter on the table, including the slicer, so the denominator is 1,000 and North shows 40 percent. ALLEXCEPT(Sales, Sales[Category]) removes all filters except the one on Category, so here it matches the first: 57.1 percent. Choose by asking which filters the denominator must keep; ALL on the whole table is a common cause of wrong shares.

Example
Sales
Region  Category  Amount
North   Laptop       400
North   Phone        100
South   Laptop       300
South   Phone        200

Total = SUM ( Sales[Amount] )
Pct Region = DIVIDE ( [Total],
    CALCULATE ( [Total], ALL ( Sales[Region] ) ) )
Pct All = DIVIDE ( [Total],
    CALCULATE ( [Total], ALL ( Sales ) ) )
Pct Cat = DIVIDE ( [Total],
    CALCULATE ( [Total], ALLEXCEPT ( Sales, Sales[Category] ) ) )

23. When would you use REMOVEFILTERS and when ALLSELECTED?

REMOVEFILTERS is ALL used only as a CALCULATE modifier: it clears filters and says so clearly, but unlike ALL it cannot be used as a table, for example inside COUNTROWS. ALLSELECTED removes the filters that come from inside the visual, its rows and columns, while keeping outer filters such as slicers and the filter pane. Use ALLSELECTED when the shares in a visual must add up to 100 percent of what the user selected, and REMOVEFILTERS when you need all categories even if a category slicer is set.

Example
Share of All Categories =
DIVIDE (
    [Total Sales],
    CALCULATE ( [Total Sales], REMOVEFILTERS ( Product[Category] ) )
)

Share of Selected =
DIVIDE (
    [Total Sales],
    CALCULATE ( [Total Sales], ALLSELECTED ( Product[Category] ) )
)

24. What is context transition? Explain it with the two calculated columns shown.

Context transition is CALCULATE turning the current row context into an equivalent filter context. In a calculated column there is a row context but no filter, so Plain shows 1,000 on every customer: the total of all sales. WithCtx wraps the same SUM in CALCULATE, which turns the current customer row into a filter that flows to Sales through the relationship, giving Asha 800, Ravi 200 and Meena blank. Every measure reference has a hidden CALCULATE around it, so using [Total Sales] in the column would also give 800, 200 and blank.

Example
Customer[Name]: Asha, Ravi, Meena

Sales
Customer  Amount
Asha         500
Asha         300
Ravi         200

-- Calculated columns on Customer
Plain   = SUM ( Sales[Amount] )
WithCtx = CALCULATE ( SUM ( Sales[Amount] ) )

25. Why does the total row of a measure sometimes not equal the sum of its rows, and how do you fix it?

The total row is not a sum of the rows: the measure runs again in the total's filter context, which here means all regions. Bonus gives North 50, South 0 and East 0, but at the total [Total Sales] is 1,000, which is above 400, so the total shows 100 instead of 50. To get the sum of the rows, iterate them yourself: Bonus Fixed loops over each region with SUMX, applies the rule per region and adds the results, giving 50. Agree with the business which total is correct before you change it.

Example
Region  Total Sales
North           500
South           300
East            200

Bonus = IF ( [Total Sales] > 400, [Total Sales] * 0.1, 0 )

Bonus Fixed =
SUMX (
    VALUES ( Sales[Region] ),
    IF ( [Total Sales] > 400, [Total Sales] * 0.1, 0 )
)

26. What is the difference between AVERAGE and AVERAGEX? What do the two measures shown return for these two days?

AVERAGE averages the values of one column, row by row: here (200 + 300 + 100 + 400) / 4 = 250, the average order value. AVERAGEX evaluates an expression for each row of a table and averages the results. Iterating the dates and computing [Total Sales] for each gives 600 for 1 April and 400 for 2 April, so average daily sales is 500. Days with no sales return blank and AVERAGEX skips blanks, so add 0 to the expression if empty days must count. Always ask: average of what?

Example
OrderDate   Amount
2025-04-01     200
2025-04-01     300
2025-04-01     100
2025-04-02     400

Avg Order = AVERAGE ( Sales[Amount] )

Avg Daily Sales =
AVERAGEX ( VALUES ( 'Date'[Date] ), [Total Sales] )

27. Why does a RANKX measure show 1 for every product, and how do you fix it?

RANKX ranks the current value against the values for each row of the table you give it, and that table is evaluated in the current filter context. If you write RANKX over Product on a visual with products on rows, each row's filter leaves only that one product in the table, so every product ranks 1. Remove the filter with ALL on the product column, as shown, so each product is compared with all of them. Use DENSE if ties should not skip numbers, and ISINSCOPE to blank the rank on the total row.

Example
Product Rank =
IF (
    ISINSCOPE ( Product[Product Name] ),
    RANKX (
        ALL ( Product[Product Name] ),
        [Total Sales], , DESC, DENSE
    )
)

28. How do you calculate last year's sales, year-on-year growth and financial-year-to-date sales for an April to March year?

SAMEPERIODLASTYEAR shifts the dates in the current filter context back one year, so Sales PY shows the same month or quarter of the previous year. YoY % divides the change by last year with DIVIDE, so periods with no history show blank instead of an error. TOTALYTD accumulates from the start of the year, and its optional year-end argument "3/31" makes the year run from 1 April to 31 March. All three need a proper date table with contiguous dates, and visuals should use that table's columns, not dates from Sales.

Example
Sales PY =
CALCULATE ( [Total Sales], SAMEPERIODLASTYEAR ( 'Date'[Date] ) )

YoY % = DIVIDE ( [Total Sales] - [Sales PY], [Sales PY] )

Sales FYTD = TOTALYTD ( [Total Sales], 'Date'[Date], "3/31" )

29. Why use variables in DAX, and what is the common mistake with them?

VAR stores the result of an expression once, so a measure that needs the same value several times computes it once and reads like a recipe: current sales, previous sales, then the result. That helps readability and often speed. The trap is that a variable is evaluated where it is defined and then becomes a constant. In the second measure CALCULATE cannot change S, so the result equals Total Sales, not the all-time total. Put the CALCULATE inside the variable definition instead.

Example
YoY Growth % =
VAR CurrentSales = [Total Sales]
VAR PrevSales =
    CALCULATE ( [Total Sales], SAMEPERIODLASTYEAR ( 'Date'[Date] ) )
RETURN
    DIVIDE ( CurrentSales - PrevSales, PrevSales )

-- Trap: S is already computed, CALCULATE cannot change it
Wrong All Time =
VAR S = [Total Sales]
RETURN CALCULATE ( S, REMOVEFILTERS ( 'Date' ) )

30. What is cross-filter direction, and when would you set a relationship to Both?

Cross-filter direction says which way filters travel along a relationship. Single, the default for one-to-many, lets the dimension filter the fact: picking a product filters Sales. Both also lets the fact filter the dimension, so a customer slicer can list only customers who bought the selected product. Both can create ambiguous filter paths, slower queries and confusing numbers, so keep relationships single and enable the other direction only inside the measure that needs it with CROSSFILTER, as shown. Often DISTINCTCOUNT of Sales[CustomerID] is simpler.

Example
Customers Who Bought =
CALCULATE (
    COUNTROWS ( Customer ),
    CROSSFILTER ( Sales[CustomerID], Customer[CustomerID], BOTH )
)

31. Sales has both an OrderDate and a ShipDate. How do you report by either date with one Date table?

Create two relationships from Date[Date]: one to Sales[OrderDate] and one to Sales[ShipDate]. Power BI allows only one active relationship between two tables, so one of them, usually ShipDate, stays inactive and shows as a dotted line. Normal measures use the active OrderDate path. For shipments, write a measure that switches on the inactive relationship with USERELATIONSHIP inside CALCULATE, as shown. If users need to slice by both dates at the same time, add a second date table for ship date instead.

Example
Sales by Ship Date =
CALCULATE (
    [Total Sales],
    USERELATIONSHIP ( Sales[ShipDate], 'Date'[Date] )
)

32. A matrix shows the same value on every row instead of a breakdown. How do you debug it?

The same number on every row means the field on rows does not filter the table the measure reads. First check the Model view: is there a relationship between the two tables, and is it active? Next check direction: a column from a table on the many side, or from another fact table, cannot filter a dimension unless the filter is set to flow that way. Then read the measure for ALL or REMOVEFILTERS on that column. For example, Targets[Region] on rows with a Sales measure repeats the grand total; use the shared Region dimension instead.

33. What is query folding, and how do you check whether it is happening?

Query folding means Power Query translates your steps into one native query, such as SQL, that the source runs, so filters and joins happen in the database and only the result travels to Power BI. It makes refresh faster and is needed for incremental refresh to work efficiently. To check, right-click a step and look at View Native Query; if it is greyed out, that step probably does not fold. Filtering rows, removing columns, grouping and merges within one database usually fold; adding an index column usually does not.

34. Each branch sends a monthly Excel file to a shared folder. How do you load them all in Power Query?

Use the Folder connector, or SharePoint Folder if the files are in SharePoint Online, which refreshes in the Service without a gateway. Filter to the right files first, as shown, then use Combine Files. Power Query creates a sample file, a parameter and a function, and applies the same steps to every file before appending them. To change the cleaning, edit the Transform Sample File query and every file follows. Watch for a file with renamed columns, which leaves nulls, and for temporary Excel lock files whose names start with ~$.

Example
let
    Source = Folder.Files("D:\Branch Reports\FY2025"),
    XlsxOnly = Table.SelectRows(
        Source,
        each [Extension] = ".xlsx"
            and not Text.StartsWith([Name], "~$")
    )
in
    XlsxOnly

35. How do you set up drill-through to a customer detail page, and what should you watch for?

Create the detail page, then drag the customer field into the Drill through area of that page's Visualizations pane; Power BI adds a back button. Users can now right-click a customer in any visual and choose Drill through to open the page filtered to that customer. The Keep all filters switch decides whether other filters, such as the selected month or region, are passed along too. Use a customer key rather than a name when two customers can share a name, and hide the page if it only makes sense through drill-through.

36. How do you build a toggle between a chart view and a table view with bookmarks, and what is the usual mistake?

Place the chart and the table in the same spot, use the Selection pane to show the chart and hide the table, and save a bookmark named Chart view; reverse the visibility and save Table view. Add two buttons whose action is Bookmark, one for each. The usual mistake is leaving the bookmark's Data option on: every click then resets the slicers to the values saved in the bookmark. Turn Data off for view toggles so only visibility changes. Group the bookmarks, and use a bookmark navigator when there are many views.

37. How do you set up dynamic row-level security so that each regional manager sees only their regions?

Keep a UserAccess table with one row per user and region, maintained by the business, instead of one role per region. Load it unrelated and hidden, and create one role whose filter on Region keeps the regions listed for the signed-in user, using USERPRINCIPALNAME, as shown. The filter on Region then flows to Sales through the normal relationship, so no bidirectional relationship is needed. Add everyone to that single role in the Service, test in Desktop with View as and another user's e-mail, and make sure the e-mails match sign-in names.

Example
-- Role: Regional Manager
-- Table filter on Region
Region[Region]
    IN CALCULATETABLE (
        VALUES ( UserAccess[Region] ),
        UserAccess[Email] = USERPRINCIPALNAME ()
    )

38. When do you need an on-premises data gateway, and what is the difference between standard and personal mode?

A gateway is needed when the Service must reach data that is not reachable over the internet: a SQL Server on the office network, files on a local or network drive, or on-premises Analysis Services. Cloud sources such as SharePoint Online or Azure SQL Database usually need none. Standard mode is shared: admins add data sources, many users and models can use it, and it supports DirectQuery and live connections. Personal mode serves one user and Import refresh only. Run a standard gateway on an always-on server, not a laptop, and cluster a second one for failover.

39. What are the workspace roles in the Power BI Service, and how does an app differ from sharing the workspace?

Workspaces have four roles. Admin manages access and settings and can delete the workspace. Member can add people with lower roles and publish or update the app. Contributor can create and edit content but not manage access. Viewer can only view, and RLS applies to them. An app packages selected reports and dashboards from a workspace for a wider audience, such as all branch managers, who never see the workspace itself. Changes reach app users only when someone updates the app, so authors can fix a report without users seeing half-done work.

40. A report page takes 15 seconds to load. How do you find out which visual is slow?

Open Performance Analyzer in Desktop, start recording and click Refresh visuals. Each visual then shows its time split into DAX query, Visual display and Other. A long DAX query points to the measure or the model, so copy the query and study it in DAX Studio. A long Visual display means too many data points or a heavy custom visual. A long Other usually means the visual waited for others, so a page with 25 visuals is the real problem. Fix the slowest first, and retest with a cleared cache, because a second run can be served from cache.

Ready to check yourself? Take the free Power BI mock test

Power BI interview questions: Hard questions (experienced)

20 questions

41. How does a boolean filter in CALCULATE interact with an existing filter on the same column, and what does KEEPFILTERS change? Use the matrix shown, with Category on rows.

A boolean filter such as Sales[Category] IN {...} is shorthand for FILTER over ALL(Sales[Category]), so it replaces any existing filter on that column. Two Cats therefore shows 1,000 on every row, even Tablet, because the row's own Category filter is overwritten. KEEPFILTERS intersects the new filter with the existing one instead: Laptop shows 700, Phone 300, Tablet blank, and the total 1,000. Use KEEPFILTERS when a measure must respect what the user has already selected on that column.

Example
Category  Total
Laptop      700
Phone       300
Tablet      150

Two Cats = CALCULATE ( [Total],
    Sales[Category] IN { "Laptop", "Phone" } )

Two Cats Keep = CALCULATE ( [Total],
    KEEPFILTERS ( Sales[Category] IN { "Laptop", "Phone" } ) )

42. What is the difference between filtering a column and filtering the whole fact table inside CALCULATE?

Laptop A filters one column: the engine works on the few distinct values of Category, which is fast, and the filter replaces any existing Category filter. Laptop B iterates every row of Sales in the current filter context and uses the surviving rows, with all their columns, as the filter. On a Phone row it returns blank, because no row is both Phone and Laptop, and on a large fact table it is slower and uses more memory. Prefer column filters, and add KEEPFILTERS when the existing selection must be respected.

Example
-- Column filter: fast, replaces the Category filter
Laptop A = CALCULATE ( [Total], Sales[Category] = "Laptop" )

-- Table filter: scans Sales, keeps existing filters
Laptop B = CALCULATE ( [Total],
    FILTER ( Sales, Sales[Category] = "Laptop" ) )

43. In the table shown, Total Amount returns 300 but Total Again returns 400. Why?

Referencing a measure inside SUMX triggers context transition on each row: the row becomes a filter on every column, Customer = Asha, Product = Pen, Amount = 50. The table has no key, so that filter matches both identical Asha rows and returns 100, and this happens for each of those two rows. The result is 100 + 100 + 200 = 400, while SUM gives 300. Avoid it by iterating the column directly, as in SUMX(Orders, Orders[Amount]), or by adding a unique key such as an order line ID. Calculated columns that use CALCULATE hit the same trap.

Example
Orders
Customer  Product  Amount
Asha      Pen          50
Asha      Pen          50
Ravi      Book        200

Total Amount = SUM ( Orders[Amount] )
Total Again  = SUMX ( Orders, [Total Amount] )

44. A product slicer shows a (Blank) item although Product has no blank values. Why, and how do VALUES and DISTINCT differ here?

Sales contains ProductIDs that do not exist in Product, a referential integrity violation. For a regular one-to-many relationship the engine adds a virtual blank row to Product so those sales still appear somewhere, and slicers show it as (Blank). VALUES includes that blank row and DISTINCT does not; ALL includes it and ALLNOBLANKROW does not, so counts can differ by one. The real fix is in the data: load the missing products, or map unknown keys to an Unknown product row in Power Query, so totals stay complete and labelled.

Example
-- Counts the blank row added for unmatched keys
With Blank Row = COUNTROWS ( VALUES ( Product[Category] ) )

-- Ignores that blank row
Without = COUNTROWS ( DISTINCT ( Product[Category] ) )

45. How do you model joint bank accounts, where one account has several customers and one customer has several accounts?

Use a bridge table, AccountCustomer, with one row per account and holder. Customer filters the bridge one-to-many, but the bridge must then filter Account, which is a hop from the many side to the one side, so set that relationship to Both or enable it with CROSSFILTER in the measures that need it. A customer slicer then reaches Account and its transactions. Expect non-additive totals: a joint account's balance appears under each holder, but the grand total counts it once, which is correct. Explain this to users, and keep integer keys on the bridge.

46. Monthly targets are set per category, but sales are recorded per product per day. How do you model and show the targets?

Do not force targets into the sales table. Load Targets at its own grain, category and month, and relate it to the dimensions at that grain: to Date through a month-start date or a many-to-many relationship on a YearMonth column, and to Product on Category through a many-to-many relationship in which Product filters Targets. Targets then work by category and month. Below that grain they mean nothing, so blank the measure when a product is filtered or days are on the visual, as shown, rather than repeat a misleading number.

Example
Target Amount =
IF (
    ISFILTERED ( Product[Product Name] )
        || ISINSCOPE ( 'Date'[Date] ),
    BLANK (),
    SUM ( Targets[Amount] )
)

47. How do you write a closing balance measure when balances are stored as daily snapshots?

Balances are semi-additive: you can add them across accounts or branches but not across time, because adding 30 daily balances means nothing. Take the balance on the last date of the period instead. LASTDATE on the Date table returns the last calendar date, such as 31 March, which is blank if that day has not loaded yet. LASTNONBLANK returns the last date that actually has data, as in the measure shown. When accounts have different last snapshot dates, use LASTNONBLANKVALUE inside SUMX over accounts so each account takes its own last value.

Example
Closing Balance =
VAR LastDay =
    LASTNONBLANK (
        'Date'[Date],
        CALCULATE ( SUM ( Balances[Amount] ) )
    )
RETURN
    CALCULATE ( SUM ( Balances[Amount] ), LastDay )

48. What exactly makes a valid date table, and why should you turn off Auto date/time?

A date table needs a date column with one row per day: unique values, no blanks and no gaps, normally covering complete years so year-to-date and prior-year results line up. Mark it as the date table so DAX treats it as the calendar, which matters most when the relationship uses an integer key such as 20250401. Auto date/time creates a hidden date table for every date column, which inflates the model, cannot be shared across facts and gives users separate hierarchies. Turn it off in Options and use one shared date table for all facts.

49. What are calculation groups, and what should you watch for when you use them for time intelligence?

A calculation group is a set of calculation items that apply a pattern to whichever measure is in the visual, through SELECTEDMEASURE. One Time Calc group with items such as Current, PY and FYTD replaces writing Sales PY, Profit PY, Orders PY and so on. You can create them in the Model view of Desktop, and doing so turns on discourage implicit measures. Every measure is affected, including ones with their own time logic, and a percent item would format a rupee measure, so set format strings per item, exclude measures with ISSELECTEDMEASURE and set precedence when groups combine.

Example
-- Calculation group: Time Calc
Current = SELECTEDMEASURE ()

PY = CALCULATE ( SELECTEDMEASURE (),
    SAMEPERIODLASTYEAR ( 'Date'[Date] ) )

FYTD = CALCULATE ( SELECTEDMEASURE (),
    DATESYTD ( 'Date'[Date], "3/31" ) )

50. When would you use field parameters instead of bookmarks to let users switch what a visual shows?

Field parameters, created under Modeling, New parameter, Fields, generate a small table like the one shown. Put it in a slicer and on the visual, and users can switch the measure, such as Sales or Profit, or the axis, such as Region or Product, in a single visual. Doing the same with bookmarks needs one visual per option, hidden visuals and buttons, which is hard to maintain as options grow. Use field parameters to swap fields, and keep bookmarks for layout changes, panels that open and close, and guided story pages.

Example
Metric = {
    ("Sales", NAMEOF ( 'Measures'[Total Sales] ), 0),
    ("Profit", NAMEOF ( 'Measures'[Total Profit] ), 1),
    ("Orders", NAMEOF ( 'Measures'[Order Count] ), 2)
}

51. How do you build row-level security for a manager hierarchy, where each manager sees their whole team below them?

Store the hierarchy in the Employee table with EmpID and ManagerID, then add a Path calculated column with PATH, which returns a chain such as 1|4|12 from the top manager down. The role filter on Employee finds the signed-in user's EmpID and keeps every row whose path contains it, so a manager sees their own rows and everyone below them at any depth. Employee then filters Sales through the usual relationship. Keep IDs unique, make sure the hierarchy has no loops, and test several levels with View as another user.

Example
-- Calculated column on Employee
Path = PATH ( Employee[EmpID], Employee[ManagerID] )

-- Role filter on Employee
VAR Me =
    LOOKUPVALUE (
        Employee[EmpID],
        Employee[Email], USERPRINCIPALNAME ()
    )
RETURN
    PATHCONTAINS ( Employee[Path], Me )

52. What are the limits of row-level security, and when do you need object-level security?

RLS applies to users with read access, such as Viewers, app users and people a report is shared with; workspace Admins, Members and Contributors are not filtered. Filters travel only in the direction of each relationship, so with a bidirectional relationship you must tick Apply security filter in both directions for RLS to flow the other way. RLS cannot hide a column such as Salary or Margin; object-level security does that, set per role with an external tool such as Tabular Editor. For those users the object behaves as if it does not exist, so visuals using it show an error.

53. How do you set up incremental refresh for a large sales table, and what makes it work well?

Create two DateTime parameters named exactly RangeStart and RangeEnd, and filter the date column with them as shown: one side inclusive and the other exclusive, so no row lands in two partitions. Then define the policy on the table in Desktop, for example store 5 years and refresh the last 10 days. After publishing, the Service creates the partitions and later refreshes only the recent ones. The filter must fold to the source, or each partition reads the whole table. Detect data changes can also skip partitions whose last-updated column has not moved.

Example
let
    Source = Sql.Database("sql01.corp.local", "SalesDW"),
    Sales = Source{[Schema = "dbo", Item = "FactSales"]}[Data],
    Filtered = Table.SelectRows(
        Sales,
        each [OrderDate] >= RangeStart and [OrderDate] < RangeEnd
    )
in
    Filtered

54. A scheduled refresh fails in the Service but works in Desktop. What are the usual causes?

Start with the error in the refresh history. Expired or missing credentials in the semantic model settings are the most common cause. Next, the gateway: is it online and up to date, and is the data source added with exactly the same server and database names as in Desktop? A Formula.Firewall error means privacy levels block combining sources; set the levels or restructure the queries. A dynamic data source, such as Web.Contents with a URL built from text, cannot refresh in the Service; keep the base URL fixed and pass the rest with RelativePath and Query, as shown.

Example
Web.Contents(
    "https://api.example.in",
    [
        RelativePath = "v1/orders",
        Query = [from = "2025-04-01"]
    ]
)

55. A refresh became slow because a query stopped folding. How do you find the breaking step and fix it?

Walk the applied steps from the top and check View Native Query on each; the first step where it is unavailable is usually the break, and every later step then runs in the Power Query engine on downloaded rows. In the query shown, the filter and column selection fold, but Table.AddIndexColumn does not, which is acceptable because it comes last. Move filters, column removal and grouping before any breaking step, avoid Table.Buffer on big sources, and push complex logic into a SQL view. Value.NativeQuery with EnableFolding can keep later steps folding.

Example
let
    Source = Sql.Database("sql01", "SalesDW"),
    Orders = Source{[Schema = "dbo", Item = "Orders"]}[Data],
    Recent = Table.SelectRows(
        Orders, each [OrderDate] >= #date(2025, 4, 1)
    ),
    Slim = Table.SelectColumns(
        Recent, {"OrderID", "OrderDate", "Amount"}
    ),
    Indexed = Table.AddIndexColumn(Slim, "Row", 1, 1)
in
    Indexed

56. An Import model is 3 GB. How do you reduce its size, and why does cardinality matter more than row count?

VertiPaq stores each column separately and compresses it with a dictionary of distinct values, so size depends mostly on how many distinct values a column has. A datetime column with seconds over three years can hold about 9.5 crore distinct values, while a date column has at most 1,096 and a time column at most 86,400. Split such columns as shown, or drop the time. Remove unused columns, especially IDs and free text, reduce decimals, turn off Auto date/time and prefer Power Query columns to DAX calculated columns. VertiPaq Analyzer shows the costliest columns.

Example
AddDate = Table.AddColumn(Source, "OrderDate",
    each DateTime.Date([OrderDateTime]), type date),
AddTime = Table.AddColumn(AddDate, "OrderTime",
    each DateTime.Time([OrderDateTime]), type time),
Slim = Table.RemoveColumns(AddTime, {"OrderDateTime"})

57. How do you use DAX Studio to find out why a measure is slow?

Copy the visual's query from Performance Analyzer, run it in DAX Studio connected to the Desktop model, and turn on Server Timings with the cache cleared. The timings split the work between the storage engine, which is multi-threaded, cached and fast at scanning columns, and the formula engine, which is single-threaded and handles complex logic. Mostly formula engine time, many storage engine queries, or CallbackDataID in them means the measure forces row-by-row work. Rewrite that part and re-run to compare. View Metrics shows table and column sizes.

58. Explain composite models and aggregations. How would you serve a fact table of 200 crore rows?

A composite model mixes storage modes. Keep the huge fact table in DirectQuery, add an Import aggregation table summarised by date, product and branch, and map it with Manage aggregations. Most visuals ask for summaries and are answered from memory; only detail queries go to the source. Set the shared dimensions to Dual so they can join either way, otherwise relationships across the two sources become limited and slower. Check aggregation hits with the Aggregate Table Rewrite Query trace event, and make sure the source is indexed for the queries that still reach it.

59. How would you organise workspaces, models and apps for a company where 12 departments build their own reports?

Separate data from reports. Put one shared semantic model per subject, such as Sales or HR, in a data workspace owned by the BI team, and endorse it as Promoted or Certified. Department authors get Build permission and create thin reports that connect live to it, so measures are defined once. Each department workspace publishes an app, with audiences if different groups need different pages. Use deployment pipelines or separate dev, test and prod workspaces, with rules to switch data sources, and keep nothing important in My workspace.

60. How would you rewrite the slow measure shown, and what general rules make DAX faster?

The first version scans the whole Sales table three times and repeats the same sum. The rewrite stores each value once in a variable, filters only the Amount column with KEEPFILTERS so existing filters still apply, and uses DIVIDE instead of the IF test. General rules: filter columns, not tables; avoid nested iterators over large tables; avoid IFERROR; compute a value once with VAR; move row-level logic into Power Query or the source; and measure the change in DAX Studio rather than guessing.

Example
-- Before
Big Order Margin % =
IF (
    SUMX ( FILTER ( Sales, Sales[Amount] > 10000 ),
        Sales[Amount] ) = 0,
    BLANK (),
    SUMX ( FILTER ( Sales, Sales[Amount] > 10000 ),
        Sales[Profit] )
        / SUMX ( FILTER ( Sales, Sales[Amount] > 10000 ),
            Sales[Amount] )
)

-- After
Big Order Margin % =
VAR BigSales = CALCULATE ( SUM ( Sales[Amount] ),
    KEEPFILTERS ( Sales[Amount] > 10000 ) )
VAR BigProfit = CALCULATE ( SUM ( Sales[Profit] ),
    KEEPFILTERS ( Sales[Amount] > 10000 ) )
RETURN
    DIVIDE ( BigProfit, BigSales )

Practice questions for November 2026

New every month

3 questions from the Power BI mock test, the way they appear in it. A new set comes on the 1st of every month. Pick your answer, then open it.

  1. FresherPower BI Basics

    In 2023 Microsoft renamed Power BI datasets. What are they called now?

    • Dataflows
    • Datamarts
    • Analysis Services cubes
    • Semantic models
    Show the answer

    Answer: Semantic models. Datasets were renamed semantic models to reflect what they hold: tables, relationships, measures and security that reports query. Dataflows, datamarts and lakehouses are separate items for preparing or storing data.

  2. Intermediate (1-5 years)Filter Context and CALCULATE

    A table visual shows Sales[Region] with the measure North Sales. What value appears in the South row?

    Sales
    Region  Product  Amount
    North   Pen         200
    North   Book        300
    South   Pen         100
    South   Bag         200
    East    Book        150
    East    Bag          50
    
    North Sales =
        CALCULATE(
            SUM(Sales[Amount]),
            Sales[Region] = "North"
        )
    • Blank (an empty cell)
    • 500
    • 300
    • 1000
    Show the answer

    Answer: 500. A Boolean filter in CALCULATE works like FILTER(ALL(Sales[Region]), ...): it removes the existing filter on Region and puts North in its place. So every row, South included, shows the North total 500.

  3. Experienced (5+ years)Row-Level Security

    Why map Microsoft Entra security groups to RLS roles rather than individual users?

    • Individual users cannot be added to an RLS role at all
    • Groups make RLS apply to workspace Admins and Members as well
    • Joiners and leavers are handled in the group, so roles need no edits
    • Using groups makes each scheduled refresh run faster
    Show the answer

    Answer: Joiners and leavers are handled in the group, so roles need no edits. Mapping groups to roles moves membership to identity management: IT adds or removes people from the group and their access follows. Individual mappings are allowed but drift and are easy to forget when someone leaves.

Take the full Power BI mock test

Ready to apply?

There are 1,619 open jobs asking for Power BI on CoreHRx right now. Create a free profile once and apply with it.