Forum Discussion

effi_go's avatar
effi_go
Frequent Visitor
7 months ago
Solved

Problem separating data by location after machines switch places in Power BI

Hi everyone,

I am working on a Power BI report that reads data directly from a SQL database. I only have read access and cannot change the database structure or data model.

 

We have test machines that write their measurement data directly into the database. Our reporting combines data from  different locations. So far, each machine has always operated at exactly one location, and therefore the location of a data record has always been identified implicitly based on the machine ID.

Recently, two machines have been physically swapped between two locations.
Let’s call them Machine A and Machine B:

  • Machine A has always been at Location X
  • Machine B has always been at Location Y
  • Now both machines have switched locations
  • Both machines keep their existing IDs
  • The way the machines write data into the database does not change (only the physical location changes)

This leads to a challenge in my Power BI report:
Because the location has always been inferred directly from the machine ID, the existing logic no longer reflects reality once the machines switch places. Historical data (before the swap) and future data (after the swap) now refer to different physical locations, although the machine IDs stay the same.

 

My question is:
How can this situation be handled within Power BI so that both historical and future data can still be evaluated correctly based on location, even though the database itself contains no explicit location information and I can't modify it?

 

Any ideas or best practices would be greatly appreciated.
Thanks!

  • 1) Create a mapping table (in Power BI)

    This can be:

    • Enter Data

    • Excel / SharePoint

    • CSV

    • Dataflow

    Example:

    MachineID Location StartDate EndDate
    AX1900-01-012024-06-30
    AY2024-07-019999-12-31
    BY1900-01-012024-06-30
    BX2024-07-019999-12-31

     

    This is effectively a Type-2 Slowly Changing Dimension, implemented outside the DB.

     

    2) Add calculated column in Fact

    Location =
    VAR d = Fact[MeasurementDate]
    VAR m = Fact[MachineID]
    RETURN
    CALCULATE (
        MAX ( MachineLocation[Location] ),
        FILTER (
            MachineLocation,
            MachineLocation[MachineID] = m
                && d >= MachineLocation[StartDate]
                && d <= COALESCE ( MachineLocation[EndDate], DATE ( 9999, 12, 31 ) )
        )
    )

     

    The solution above is given this way because you told you cannot change anything in DB, if you could the best approach would be adding ID to Fact and Type-2 Slowly Changing Dimension as a new dimention and use those by giving relation between them.

  • Hi @effi_go,

      and  are completely correct; this is a classic Slowly Changing Dimension (SCD) Type 2 scenario. Since you cannot modify the database, creating this "Logic Layer" inside Power BI is the only way to solve it.Here is the "Complete" guide to implementing this, including the visual logic and a performance tip for the DAX formula.

    1. The Concept: Time-Based Lookup

    You are moving from a Static relationship (Machine = Location) to a Temporal relationship (Machine + Time = Location).

    You need a standalone "Mapping Table" that defines the "Valid From" and "Valid To" dates for each machine's location.

    2. The Implementation (DAX Calculated Column)

    The DAX solution provided by @cengizhanarslan is generally the most performant method for this "Range Lookup" scenario in Power BI, as Power Query lookups can be very slow with large datasets.

    However, to make the formula robust against missing End Dates (active records), use this refined pattern:

    Step 1: Create the Mapping Table (Use "Enter Data" or an Excel sheet as suggested)

    • MachineID | Location | StartDate | EndDate

    • A | X | 1/1/2020 | 6/30/2024

    • A | Y | 7/1/2024 | 12/31/9999 (Use a far future date for "Active")

      Step 2: The Calculated Column Add this column to your Fact Table (where your measurements are). Note: Ensure there is NO active relationship between your Fact Table and the Mapping Table.

       
      Calculated Location = 
      VAR CurrentDate = 'FactTable'[MeasurementDate]
      VAR CurrentMachine = 'FactTable'[MachineID]
      RETURN
          CALCULATE (
              // We take MAX to return the single text value found
              MAX ( 'LocationMapping'[Location] ),
              FILTER (
                  'LocationMapping',
                  'LocationMapping'[MachineID] = CurrentMachine &&
                  'LocationMapping'[StartDate] <= CurrentDate &&
                  // Handle NULL EndDates as "Today" or Future
                  COALESCE('LocationMapping'[EndDate], DATE(9999,12,31)) >= CurrentDate
              )
          )

      3. Why not Power Query?

        mentioned that doing this in Power Query "could get slow fast". This is because performing a "Non-Equi Join" (joining on a date range rather than an exact match) forces Power Query to scan the entire mapping table for every single row in your Main Table. DAX (specifically the VertiPaq engine) is much faster at handling these in-memory range filters.

      Summary Checklist

      1. Create the Mapping Table with Start/End dates.

      2. Use 12/31/9999 for the End Date of the current location.

      3. Use the Calculated Column approach (not a Measure) so you can use the Location as a slicer/axis in your charts.


        If this breakdown helps clarify the "SCD Type 2" implementation, a Kudos is appreciated!
        This response was assisted by AI for translation and formatting purposes.

      4.  

      5.  

      tayloramy

    •  

    •  

    cengizhanarslan

6 Replies

  • 1) Create a mapping table (in Power BI)

    This can be:

    • Enter Data

    • Excel / SharePoint

    • CSV

    • Dataflow

    Example:

    MachineID Location StartDate EndDate
    AX1900-01-012024-06-30
    AY2024-07-019999-12-31
    BY1900-01-012024-06-30
    BX2024-07-019999-12-31

     

    This is effectively a Type-2 Slowly Changing Dimension, implemented outside the DB.

     

    2) Add calculated column in Fact

    Location =
    VAR d = Fact[MeasurementDate]
    VAR m = Fact[MachineID]
    RETURN
    CALCULATE (
        MAX ( MachineLocation[Location] ),
        FILTER (
            MachineLocation,
            MachineLocation[MachineID] = m
                && d >= MachineLocation[StartDate]
                && d <= COALESCE ( MachineLocation[EndDate], DATE ( 9999, 12, 31 ) )
        )
    )

     

    The solution above is given this way because you told you cannot change anything in DB, if you could the best approach would be adding ID to Fact and Type-2 Slowly Changing Dimension as a new dimention and use those by giving relation between them.

    • effi_go's avatar
      effi_go
      Frequent Visitor
      Thank you so much for your help!
      Your explanation makes a lot of sense. I'm going to try to implement this approach into my report and will let you know, if it works out. 
    • effi_go's avatar
      effi_go
      Frequent Visitor

      Thanks again for your help! I've deceided to mark burakkaragoz's reply as the solution because it provided me with more details, which ended up helping me at completly implementing the SCD-method.

  • Hi @effi_go,

      and  are completely correct; this is a classic Slowly Changing Dimension (SCD) Type 2 scenario. Since you cannot modify the database, creating this "Logic Layer" inside Power BI is the only way to solve it.Here is the "Complete" guide to implementing this, including the visual logic and a performance tip for the DAX formula.

    1. The Concept: Time-Based Lookup

    You are moving from a Static relationship (Machine = Location) to a Temporal relationship (Machine + Time = Location).

    You need a standalone "Mapping Table" that defines the "Valid From" and "Valid To" dates for each machine's location.

    2. The Implementation (DAX Calculated Column)

    The DAX solution provided by @cengizhanarslan is generally the most performant method for this "Range Lookup" scenario in Power BI, as Power Query lookups can be very slow with large datasets.

    However, to make the formula robust against missing End Dates (active records), use this refined pattern:

    Step 1: Create the Mapping Table (Use "Enter Data" or an Excel sheet as suggested)

    • MachineID | Location | StartDate | EndDate

    • A | X | 1/1/2020 | 6/30/2024

    • A | Y | 7/1/2024 | 12/31/9999 (Use a far future date for "Active")

      Step 2: The Calculated Column Add this column to your Fact Table (where your measurements are). Note: Ensure there is NO active relationship between your Fact Table and the Mapping Table.

       
      Calculated Location = 
      VAR CurrentDate = 'FactTable'[MeasurementDate]
      VAR CurrentMachine = 'FactTable'[MachineID]
      RETURN
          CALCULATE (
              // We take MAX to return the single text value found
              MAX ( 'LocationMapping'[Location] ),
              FILTER (
                  'LocationMapping',
                  'LocationMapping'[MachineID] = CurrentMachine &&
                  'LocationMapping'[StartDate] <= CurrentDate &&
                  // Handle NULL EndDates as "Today" or Future
                  COALESCE('LocationMapping'[EndDate], DATE(9999,12,31)) >= CurrentDate
              )
          )

      3. Why not Power Query?

        mentioned that doing this in Power Query "could get slow fast". This is because performing a "Non-Equi Join" (joining on a date range rather than an exact match) forces Power Query to scan the entire mapping table for every single row in your Main Table. DAX (specifically the VertiPaq engine) is much faster at handling these in-memory range filters.

      Summary Checklist

      1. Create the Mapping Table with Start/End dates.

      2. Use 12/31/9999 for the End Date of the current location.

      3. Use the Calculated Column approach (not a Measure) so you can use the Location as a slicer/axis in your charts.


        If this breakdown helps clarify the "SCD Type 2" implementation, a Kudos is appreciated!
        This response was assisted by AI for translation and formatting purposes.

      4.  

      5.  

      tayloramy

    •  

    •  

    cengizhanarslan

    • effi_go's avatar
      effi_go
      Frequent Visitor
      Thank you so much for this detailed explanation. It helped me a lot in implementing the necessary changes to my report!