1. Lighthouse

Level 4 · Merge a discount table, then price every line

The request

From Chloe Gutierrez, Account Executive

“A few business accounts have contract discounts, and they're in contract_discounts.xlsx (I've loaded it as a query called Discounts). Can you apply them to the business web orders from Sept 1–10 so I see what each line really bills? Accounts that aren't on the list pay full price.”

Your goal

Merge the Discounts query on customer_code and expand its discount column. Customers who aren't on the list get null: replace those nulls with 0. Then add total_after_discount = line_total × (1 − discount).

  • Show exactly order_id order_date customer_code product line_total discount total_after_discountnot done yet
  • 25 rowsnot done yet

Your sheet

Excel
The sheet for this level
order_idorder_datecustomer_codeproductline_total
1108102025-09-02C01335Vale Enamel Bowl Set11.99
2108102025-09-02C01335Spruce Wool Duvet Cover267.96
3108102025-09-02C01335Sable Concrete Adirondack Chair101.98
4108162025-09-03C00528Nantucket Brass Wall Mirror53.97
5108402025-09-04C01355Sable Linen Table Lamp92.99
6108402025-09-04C01355Fairhaven Stoneware Cutting Board425.94
7108492025-09-06C00012Bramble Ceramic Floor Lamp31.99
8108492025-09-06C00012Birch Brass Floor Mirror167.92
9108492025-09-06C00012Thatcher Oak Candle35.98
10108492025-09-06C00012Harbor Wool Knit Throw231.92
11108552025-09-07C01334Vale Enamel Bowl Set11.99
12108552025-09-07C01334Harbor Wool Knit Throw463.84
13108552025-09-07C01334Pine Cotton Area Rug1112
14108582025-09-07C00026Harbor Wool Knit Throw86.97
15108582025-09-07C00026Sable Concrete Adirondack Chair50.99
16108582025-09-07C00026Dune Black Metal Floor Lamp207.96
17108582025-09-07C00026Delancey Black Metal Wall Sconce109.98
18108592025-09-07C01404Willow Acacia Knife Block107.98
19108592025-09-07C01404Bramble Percale Quilt417
20108592025-09-07C01404Rowan Ceramic Chandelier1134
21108592025-09-07C01404Delancey Brass Vase79.96
22108852025-09-09C00607Cove Wool Lumbar Pillow105.98
23108852025-09-09C00607Vale Enamel Bowl Set23.98
24108852025-09-09C00607Cedar Cast Iron Tumbler Set159.98
25108852025-09-09C00607Bramble Percale Quilt417

Loading the editor…

    ResultPress Check to compare the query result

    Mote checks your result

    Press Check. Each row of the result that matches becomes a firefly in your lantern.

    The lesson

    In a worksheet you bring a value across from another table with XLOOKUP or VLOOKUP, one formula per row. Power Query does the same job for the whole table at once with Merge Queries. Chloe’s discount list is a second query; the order lines are the first. Merge matches them on the customer code.

    Two queries, one key

    The order lines have 25 rows for 8 business customers. The Discounts query has 6 rows:

    customer_code discount
    C01335 0.10
    C01355 0.05
    C00012 0.10
    C01404 0.05
    C00288 0.10
    C00534 0.05

    Four of these customers ordered in Sept 1–10. C00288 and C00534 are on the list but did not order, which is normal: a lookup table can hold keys you won’t need. Four customers who did order (C00528, C01334, C00026, C00607) have no contract.

    Merge queries: Discounts on customer_code, expand discount

    In Excel: Home → Merge Queries, pick Discounts in the second drop-down, click customer_code in both tables, keep Join Kind: Left Outer (all from first, matching from second), OK. Power Query adds a column full of Table values; click the expand icon on its header, tick discount, untick “Use original column name as prefix”, OK.

    Left outer: every line stays

    A left outer join keeps every row of the first query. When a key has no match, the new columns are null, Power Query’s empty value. That is the same situation as an XLOOKUP returning #N/A, except that null does not shout. Here 12 of the 25 lines come back with a null discount.

    The match is exact and case-sensitive: c01335 would not find C01335, and a code with a trailing space would not either. When a merge finds fewer matches than you expect, check the keys with Trim and Uppercase steps on both sides. The Merge dialog helps: at the bottom it says how many rows matched (“The selection matches 13 of 25 rows”).

    Null is not zero

    Replace values: discount null with 0

    In M, arithmetic with null gives null: 100 * (1 - null) is null, not 100. So before the total, turn “no contract” into an explicit 0. In Excel: select the discount column, Transform → Replace Values, Value To Find null, Replace With 0.

    Add column: total_after_discount = [line_total] * (1 - [discount])

    On the first line, C01335’s Vale Enamel Bowl Set: 11.99 × (1 − 0.10) = 10.79. On order 10816, C00528 has no contract, so the line keeps its 53.97.

    The M behind the steps

    #"Merged Queries" = Table.NestedJoin(Source, {"customer_code"}, Discounts, {"customer_code"},
        "Discounts", JoinKind.LeftOuter),
    #"Expanded Discounts" = Table.ExpandTableColumn(#"Merged Queries", "Discounts", {"discount"}, {"discount"}),
    #"Replaced Value" = Table.ReplaceValue(#"Expanded Discounts", null, 0, Replacer.ReplaceValue, {"discount"}),
    #"Added Custom" = Table.AddColumn(#"Replaced Value", "total_after_discount", each [line_total] * (1 - [discount]))

    A merge is two steps in real Excel, the join and the expand. This practice editor folds them into one line.

    Common mistakes

    • Skipping the null replacement. 12 lines get a null total, and every sum built on them is too low.
    • Choosing Inner join. It keeps only the 13 lines with a contract and silently drops the rest of the orders.
    • Duplicate keys in the lookup table. If a customer appeared twice in Discounts, Power Query would repeat that customer’s order lines once per match. (This practice editor takes the first match; real Excel duplicates rows.) Remove duplicates on the key in the lookup query first.
    • Typing the discount as 10 instead of 0.10. 1 - 10 is −9. Know whether a rate is a fraction or a percentage before you multiply.

    Pick what may run on this site. You can change this any time from "Cookie settings" at the bottom of every page.