Ravindra BagaleCourses & study guides मराठी Track your progress

How to Clean Messy Sales Data in Power BI Power Query

You download an orders file, load it into Power BI and build a chart. The total looks fine, so you send it. Next morning someone asks why one order is counted twice, why the first row of the table says "Blinkit Maharashtra orders export", and why the sales column will not add up. The chart was never the problem. The data was. In this chapter you clean a messy orders file in Power Query before any visual touches it, and you learn the one rule that decides which rows you may delete and which you must keep.

What you'll learn in this chapter

  • Load a CSV with Get data › Text/CSV › Transform Data
  • Remove Top Rows and Use First Row as Headers
  • ID columns vs metric columns: what to delete
  • Remove blank and duplicate order IDs
  • Replace NA with null, not 0
  • Extract the number before "$"
  • Set Whole Number, Decimal and Date types
  • Check the row count after Close & Apply

Practice files: blinkit-orders-small-raw.csv (the 12 rows used on this page) and blinkit-orders-raw.csv (315 rows with the same kinds of mess, for the practice task).

Made-up data: every order, product, store and number here is fictional practice data. The file imitates an export from a quick-commerce app such as Blinkit in Maharashtra cities, but no real order, shop or person is used. Amounts are in ₹ and dates are written DD-MM-YYYY.

1. The problem

Here is the small file opened in Notepad. It has the mess you will meet in real exports:

Line What you see
1 Blinkit Maharashtra orders export (fictional practice data),,,,,,,,,,,, – a title, not data
2 order_id,product_id,store_id,city,order_date,sales,price,revenue,stock,promo_type,promo_bin,delivery_date,Column13 – the real headers
3 onwards 12 order rows, some blank, some repeated, some with NA

If you load this straight into a report:

  1. Power BI calls the columns Column1, Column2 … because the first line is a title.
  2. Order BLK1003 and BLK1006 are counted twice.
  3. "2$" is text, so the sales column cannot be summed.
  4. "NA" in price makes the column text, or gives errors when you change it to a number.

2. The idea in simple words

Power Query is the kitchen; the report is the dining table. You wash and cut the vegetables in the kitchen, once, and every dish served afterwards is clean. Every cleaning action you take is saved as a step, and Power BI replays the steps each time you refresh.

The one rule that decides what to delete:

Column type Examples Blank / NA Duplicates
Primary ID (one row = one of these) order_id delete the row delete the extra rows
Foreign ID (points to another table) product_id, store_id delete the row keep (one product sells many times)
Metric (numbers you add or average) price, revenue, stock, sales keep the row, replace NA with null keep

Why keep the row when a metric is missing? Because the order still happened. If revenue is unknown for one order, the order still counts in "Total orders", its units still count in "Sales" and its city still counts in a city chart. Deleting the row throws all of that away.

Why null and not 0? Null means "not known". Power BI's SUM and AVERAGE skip nulls. A 0 is a real number: it says the price was zero, and it pulls every average down.

Primary IDorder_idblank → delete rowduplicate → delete extra rowsForeign IDproduct_id / store_idblank / NA → delete rowduplicate → keepMetricprice / revenue / stockNA → null, keep rownever delete the rowIllustration (fictional data)

Figure 1. Which rows to delete: blank or duplicate primary IDs and blank foreign IDs go; rows with a missing metric stay, with null in the empty cell (illustration).

3. The data

The 12 order rows (line 1 and the header line are not shown). The cells that need attention are in bold:

# order_id product_id store_id city order_date sales price revenue stock
1 BLK1001 P101 PUN01 Pune 05-04-2025 2$ 120 240 35
2 BLK1002 P102 NSK01 Nashik 05-04-2025 1$ 450 450 12
3 BLK1003 P103 SLP01 Solapur 18-04-2025 3$ NA 270 20
4 BLK1003 P103 SLP01 Solapur 18-04-2025 3$ NA 270 20
5 (blank) P104 PUN01 Pune 20-04-2025 1$ 60 60 50
6 BLK1004 NA KOP01 Kolhapur 02-05-2025 2$ 80 160 18
7 BLK1005 P101 PUN01 Pune 05-05-2025 4$ 120 NA 33
8 BLK1006 P105 NSK01 Nashik 05-05-2025 1$ 999 999 7
9 BLK1007 (blank) SLP01 Solapur 12-06-2025 2$ 90 180 25
10 BLK1008 P102 KOP01 Kolhapur 21-06-2025 2$ 450 900 10
11 BLK1009 P103 PUN01 Pune 05-07-2025 5$ 90 450 NA
12 BLK1006 P105 NSK01 Nashik 05-05-2025 1$ 999 999 7

The file also has promo_type, promo_bin, delivery_date and an empty Column13. You will remove promo_bin and Column13 because no report needs them.

Before you click anything, predict with a pencil: which rows will survive? (Answer in section 5.)

4. Step by step

Load the file

  1. Open Power BI Desktop. Home › Get data › Text/CSV.
  2. Pick blinkit-orders-small-raw.csv and click Open.
  3. In the preview window click Transform Data (not Load). The Power Query Editor opens.

Fix the top of the table

  1. Home › Remove Rows › Remove Top Rows, type 1, OK. The title line is gone.
  2. Home › Use First Row as Headers. The columns are now called order_id, product_id and so on.

Primary ID: order_id

  1. Click the filter arrow on order_id, untick (blank), OK. Row 5 goes.
  2. Click the order_id header to select it. Home › Remove Rows › Remove Duplicates. The second BLK1003 and the second BLK1006 go.

Foreign ID: product_id

  1. Click the filter arrow on product_id, untick (blank) and NA, OK. Rows 6 and 9 go.
  2. Do not remove duplicates here. P101, P102, P103 and P105 each sell more than once, and that is correct.

Remove columns you do not need

  1. Ctrl+click the promo_bin and Column13 headers, right-click › Remove Columns.

Metric columns: keep the rows, fix the values

  1. Right-click the sales header › Transform › Extract › Text Before Delimiter, type $, OK. "2$" becomes "2".
  2. Click the type icon (ABC) at the left of the sales header › Whole Number.
  3. Right-click the price header › Replace Values. Value To Find: NA. Replace With: leave it empty. Open Advanced options and tick Match entire cell contents. OK.
  4. Change the price type to Decimal Number. The empty cell now shows null.
  5. Do steps 13 and 14 for revenue.
  6. Do step 13 for stock, then set its type to Whole Number.

Dates written DD-MM-YYYY

  1. Right-click order_date › Change Type › Using Locale…. Data Type: Date. Locale: English (India). OK.
  2. Do the same for delivery_date.

Load and check

  1. Home › Close & Apply.
  2. Go to Table view (the grid icon on the left) and read the row count at the bottom of the screen.
1. Remove top row + headers12 rows2. Blank order_id removed11 rows3. Duplicates removed9 rows4. Blank/NA product_id removed7 rows5. Fix sales, price, revenue, stock7 rows6. Dates with locale + Close & Apply7 rowsIllustration (fictional data)

Figure 2. The cleaning steps in order, with the row count after each one, for the 12-row file (illustration).

5. Your result should look like this

Table view shows 7 rows:

order_id product_id store_id city order_date sales price revenue stock
BLK1001 P101 PUN01 Pune 05-04-2025 2 120 240 35
BLK1002 P102 NSK01 Nashik 05-04-2025 1 450 450 12
BLK1003 P103 SLP01 Solapur 18-04-2025 3 null 270 20
BLK1005 P101 PUN01 Pune 05-05-2025 4 120 null 33
BLK1006 P105 NSK01 Nashik 05-05-2025 1 999 999 7
BLK1008 P102 KOP01 Kolhapur 21-06-2025 2 450 900 10
BLK1009 P103 PUN01 Pune 05-07-2025 5 90 450 null

(Table view shows the dates in your computer's date format; the values are the same dates.)

Check these totals by hand from the table:

Check Value
Rows 7
Sum of sales (units) 2 + 1 + 3 + 4 + 1 + 2 + 5 = 18
Sum of revenue 240 + 450 + 270 + 999 + 900 + 450 = ₹3,309 (BLK1005 is null and skipped)
Average price (120 + 450 + 120 + 999 + 450 + 90) ÷ 6 = ₹371.50

6. What happened

The row count tells the story:

Step Rows left Why
After headers 12 the title line is gone, all orders are still there
Blank order_id removed 11 a row with no order number cannot be counted as an order
Duplicate order_id removed 9 BLK1003 and BLK1006 appeared twice
Blank / NA product_id removed 7 an order line that points to no product cannot be linked to the product table
Metric steps (sales, price, revenue, stock) 7 values were fixed; no row was deleted

The last line is the one to remember. The metric steps changed values, never the number of rows.

Classroom line

Never leave NA in an ID column. Never leave null there either.

7. Explore further

  • Every click is a step. Look at Applied Steps on the right: Source, Promoted Headers, Filtered Rows, Removed Duplicates and so on. Click any step to see the data at that moment. The next chapter uses this to fix an error.
  • Blank cells become null on their own. When a number column has an empty cell, the type change turns it into null. Text such as "NA", "-" or "n/a" does not; you must replace it first.
  • Why "Match entire cell contents"? Without it, Replace Values also replaces the letters NA inside a longer value in the same column, so a value such as "NA-12" would turn into "-12". With the box ticked, only cells that are exactly NA change.
  • Why Using Locale for dates? A computer set to English (United States) reads 05-04-2025 as 4 May. Telling Power Query the file is English (India) makes it 5 April. Check one date you know after the change.
  • Your computer matters for big files. Power BI Desktop runs on Windows and holds the data in memory, so large files need RAM. A hexa-core processor is one CPU with 6 cores; more cores and more RAM help refresh speed. If Power BI freezes, open Task Manager (Ctrl+Shift+Esc), and end the Power BI task only if it stays "Not responding", because unsaved work is lost.

8. Common mistakes

Wrong result Reason Fix
Column names are Column1, Column2 … The title line was used as the header Remove Top Rows (1), then Use First Row as Headers
6 rows instead of 7 NA was filtered out of price with the filter arrow, which deletes BLK1003 Delete that Filtered Rows step; use Replace Values on price
5 rows instead of 7 NA filtered out of price and revenue Same fix for both columns
Average price ₹318.43 instead of ₹371.50 NA was replaced with 0, so 2,229 is divided by 7, not 6 Replace NA with an empty value so it becomes null
Product IDs P101, P102 … appear once each and orders go missing Remove Duplicates was run on product_id Remove duplicates only on the primary ID
sales still left-aligned (text) The "$" was removed but the type was not changed Set sales to Whole Number
Dates like 05-04-2025 show as 4 May Type changed with the computer's US locale Change Type › Using Locale › English (India)

Classroom line

If you filter this out, the whole row goes, not just the one cell.

Ravindra Bagale's Tip

Before you click Close & Apply, write down how many rows you expect and why. If Table view shows fewer, open Applied Steps and click each step from the top until the count drops: the step where it drops is the step that deleted good rows.

9. Practise on your own

Practice task

Clean blinkit-orders-raw.csv (315 order rows) with the same steps.

  1. How many rows does Table view show?
  2. What is the sum of sales (units)?
  3. What is the sum of revenue?
  4. How many nulls are in price, revenue and stock?

Hints: the file has 12 blank order IDs and 15 repeated order rows. Some revenue cells are empty, not NA: they become null without any replace.

Show solution
Step Rows
After headers 315
Blank order_id removed 303
Duplicates removed 288
Blank / NA product_id removed 274
  1. 274 rows.
  2. Sum of sales: 664 units.
  3. Sum of revenue: ₹1,69,509 (Power BI shows 169,509 with the default format).
  4. price: 18 nulls, revenue: 22 nulls (14 were NA, 8 were empty), stock: 10 nulls.

If you got 256 rows, you filtered NA out of price. If you got 234, you filtered NA out of price and revenue.

10. Think like a professional

  • Business view. A missing revenue value is a question for the source team, not a reason to lose the order. Keep the row, show the null count in your notes ("22 orders have no revenue in the export") and ask the team to fix it at the source.
  • Performance. Remove unwanted columns early. Fewer columns mean a smaller model and faster refresh.
  • Maintenance. Rename steps you will need to find again (right-click a step › Rename, for example "Removed blank order_id"). Next month's file goes through the same steps on refresh.
  • Check every refresh. Keep a row-count card on a hidden check page. A sudden drop after refresh means the export changed.

Interview questions

  1. Which rows do you delete when an ID is blank, and which when a metric is blank? Delete rows with a blank primary or foreign ID; keep rows with a blank metric and leave the metric as null.
  2. Why replace NA with null rather than 0? Null is skipped by SUM and AVERAGE; 0 is counted and makes averages wrong.
  3. Where do you remove duplicates? Only on the primary key, such as order_id.
  4. Why use Change Type with Locale? So DD-MM-YYYY dates are read as day-month, whatever the computer's region setting is.

Recap

In short

  1. Load with Transform Data, then Remove Top Rows and Use First Row as Headers.
  2. Primary ID: remove blanks and duplicates. Foreign ID: remove blanks, keep duplicates.
  3. Metric columns: never delete rows; replace NA with null.
  4. Extract the number before "$" and set the right types; use English (India) for dates.
  5. Check the row count: 12 → 11 → 9 → 7 for the small file.

Ravi Sir's Cards for this lesson

मराठी cards