Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
5 years ago
Solved

M formula that references other rows in same query

I made a DAX calculated column version of this formula that uses LOOKUPVALUE(), but I'm trying to figure out a way to create it in M.

 

This is a simplified version of a data table that I have. My data has nothing to do with sports but I wanted to make up a fake problem that would be similar to my problem. These three fake schools all have both a swim team and a water polo team, but not every school has it's own pool on-campus.

 

SchoolPlayerSportSchool has Pool?Year Athlete Started on TeamYear Athlete Left Team
WestfieldSherril TackettSwimY20082011
WestfieldMaxima ConverseWater Polo 20072008
SpringDonnetta CoppedgeSwimN20162019
SpringWaltraud GamblinWater Polo 20022005
KleinMarya PickneySwimY20162020
KleinRaguel DorazioWater Polo 20192020
WestfieldThea HartlSwimY20092010
WestfieldWilda VerdiWater Polo 20032006
SpringBok McpeekSwimN20162020
SpringJerilyn ChaversWater Polo 20122015
KleinKimberely DiblasiSwimY20142018
KleinMyriam OvittWater Polo 20112012
WestfieldLazaro FelchSwimY20122013
KleinTula McpeakSwimY20022003
WestfieldChristi JamersonWater Polo 20072011

 

You will notice the only rows of the data table that contain information on whether a school has a pool are in the rows where the Sport column has the string "Swim" and there is no pool data on the rows where the Sport column has "Water polo." For certain formulas we might want to know if a school has both a water polo team and it's own pool on-campus. 

In M, I would like to create a new column "Pool Info" that finds the "School Has Pool" marker (which is currently only available on the "Swim" rows) and puts it on every row, like so:

SchoolPlayerSportSchool has Pool?Year Athlete Started on TeamYear Athlete Left TeamPool Info
WestfieldSherril TackettSwimY20082011Y
WestfieldMaxima ConverseWater Polo 20072008Y
SpringDonnetta CoppedgeSwimN20162019N
SpringWaltraud GamblinWater Polo 20022005N
KleinMarya PickneySwimY20162020Y
KleinRaguel DorazioWater Polo 20192020Y
WestfieldThea HartlSwimY20092010Y
WestfieldWilda VerdiWater Polo 20032006Y
SpringBok McpeekSwimN20162020N
SpringJerilyn ChaversWater Polo 20122015N
KleinKimberely DiblasiSwimY20142018Y
KleinMyriam OvittWater Polo 20112012Y
WestfieldLazaro FelchSwimY20122013Y
KleinTula McpeakSwimY20022003Y
WestfieldChristi JamersonWater Polo 20072011Y


In the actual data I'm dealing with, I have other calculations that depend on the pool information, and it's helpful to have that pool information on every row (instead of just on the "Swim" rows).

I made a DAX calculated column which works fine for me, but I am wondering if there is a way to achieve this in M/power query.

Pool_Info =
LOOKUPVALUE(
'Athletics'[School has Pool?], // Return the "School has Pool?" string
'Athletics'[Sport], // Go to the column "Sport"
"Swim", // Find a row that has the string "Swim"
'Athletics'[School], // the same school on the "Swim" row should match...
'Athletics'[School], // ... the school on the current row
BLANK() // If there is no school and "Swim" match, return a blank
)

 

- Why filtering won't work: My fake table is small, but my real data has tens of thousands of rows, thousands of distinct items in Col A, a dozen different items in col C, and several variations on my issue with rows not having "pool" information... I also am later going to write formulas where I need to have that "Pool" information in every row.

 

- Merging a query with itself, then removing the nulls: This would work fine if I only had one column with the "Pool" problem--merge a table with itself and remove the rows with nulls in the new Pool column so I don't have duplicate rows with nulls.

However, the issue is that I have several columns with the equivalent of the pool problem (ie there's a "Baseball diamond" column that only has information in the "Baseball" rows but not the "Softball" rows, there's a "Football equipment" column that only has information in the "Junior Varsity Football" rows but not the "Varsity Football" rows, etc). 
I was considering referencing several queries to a merged-with-itself-table, with one query per column (one query with the Baseball Diamond column that has information for both baseball and softball rows, one query with the Football Equipment column for both varsity and junior varsity football rows, etc) but I worry that this could be a huge amount of data that could become a performance issue, possibly more than my current solution of creating a DAX LOOKUPVALUE() column for each of these scenarios. What do you think?

I hope I've explained this clearly. Does anyone have pointers?

  • Jakinta's avatar
    Jakinta
    5 years ago
    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("lZRBb9pAEIX/yohzDsZAQo6BqG1IaFFAQSjKYbAn9oj1Ll2vaZ1f37WNgw22ox7Q4MO3b+fNm3197T0KYtm76s1RpwgL9naSUvu9RkMaFkoo+wHHn+v0r/PiOr23qxP8jEFCAu6Vxg/OgOUfjmzZnLjbJu6Roy1pEinc81ZgzI3osCjjGjpPNWMEvw5sTMd1+0Vxa+wqEQhzb0+4axJ03KIMcuiJIpVBMxVKmKhUoPTt5wRj2qIQR2pTIIU7fadGrpS01m4ozMTUu6lgULZ29KiKvfABJdxplKZNrz8qyk0NXIYWQYIJaz+mHGmUdQpjnTo98+CZAz//3yw6ro6yxO4OpFNYGgyCr/RG9dsa2tsLw0OE3Co5LMNXk5QYG/QYYWoBkm26bhECtz7PBUbWG5sDO08SW0yi1qkOy+FeuMwwQW0E/V/LC534JD07IYHerjUV/bL3Kmt3TJkQbRJVRPqLRJ3NaIbe70SkEqaaMFathtWDsdxrlkEuLSUZY+1W+z35AZ2W5+f5A3HM8ie7RmE0Jj58x2gr8i1sWdly+0b1AyZql68s7TpUj/1+QjPSnPcboo1n3PFOuOU+ZfyaYvPOJPx8zKTtIbCyk6L8qbl8L8blvM7hOf7lKPNLZvLU0fRNedL5EauQEH5kIWuUvq0+OFVuzcJHeCHtc4fsoJrsKv6EH6gVfCPhhU3CpWGDC3Iaao7tYszsfukiZN1NZ769/QM=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [School = _t, Player = _t, Sport = _t, #"School has Pool?" = _t, #"School Has Baseball Field?" = _t, #"Year Athlete Started on Team" = _t, #"Year Athlete Left Team" = _t]),
        #"Grouped Rows" = Table.Group(Source, {"School"}, {{"Gr", each _, type table }, {"Pool Info", each List.Max([#"School has Pool?"]), type nullable text}, {"Baseball Fielad Info", each List.Max([#"School Has Baseball Field?"]), type nullable text}}),
        #"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"School"}),
        #"Expanded Gr" = Table.ExpandTableColumn(#"Removed Columns", "Gr", Table.ColumnNames ( #"Removed Columns"[Gr]{0}))
    in
        #"Expanded Gr"

8 Replies

  • Jakinta's avatar
    Jakinta
    Solution Sage

    You can achieve that pretty easy in M with 2 steps.

    1. Add conditional Column.

    2. Fill Down.

     

    #"Added Custom" = Table.AddColumn( PriorStepName , "Team Pool Info", each if [#"School has Pool?"] = "Y" then "Y" else if [#"School has Pool?"] = "N" then "N" else null),
     #"Filled Down" = Table.FillDown(#"Added Custom",{"Team Pool Info"})

     

    • Anonymous's avatar
      Anonymous
      Not applicable

      Thank you for your response Jakinta! 

       

      There is only one issue with this solution. I will add more details about my situation--I over-simplified my hypothetical because I worried about providing too much information, and I should have provided more details. I apologize about this!

       

      Earlier I mentioned that there are other columns/sports with the "Pool" problem. In the table below, I've added another school, Lemon, which does not have a swim team or water polo team and so it doesn't have any pool information. Lemon does not have a pool. When I use the fill down solution however and sort the schools by school name, Lemon gets filled in with an inaccurate "Y" answer in the Pool Info column because the school before it has a pool (even though Lemon doesn't have a pool--and because Lemon doesn't have any swim team, they don't have a column with a "Y" or "N" to stop the fill down). 

       

      I also added a column for the baseball field--Lemon is the only school with a baseball team and softball team, so they're the only ones with baseball or softball information, but using the fill-down method, the other schools inaccurately have it listed that they have a baseball field when they haven't provided any data in that column: 

       

       

      SchoolPlayerSportSchool has Pool?School Has Baseball Field?Year Athlete Started on TeamYear Athlete Left TeamPool InfoBaseball Field Info
      KleinMarya PickneyWater Polo  20162020  
      KleinRaguel DorazioSwimY 20192020Y 
      KleinKimberely DiblasiSwimY 20142018Y 
      KleinMyriam OvittWater Polo  20112012Y 
      KleinTula McpeakSwimY 20022003Y 
      LemonJohn BoylandBaseball Y20062010YY
      LemonTonya YehSoftball  20182019YY
      LemonVivan ArantBaseball Y20152017YY
      LemonShantae BirdsellSoftball  20042007YY
      LemonJc RigdonBaseball Y20182020YY
      LemonAvery StaggSoftball  20042005YY
      LemonStephan ImaiBaseball Y20142016YY
      LemonAnastacia CallenSoftball  20212023YY
      LemonPamella MandelbaumBaseball Y20042006YY
      LemonShanti BartleSoftball  20042005YY
      LemonPrudence BlackSoftball  20112014YY
      LemonDorotha BoomerSoftball  20182020YY
      LemonJacqulyn CreasonSoftball  20042007YY
      SpringDonnetta CoppedgeSwimN 20162019NY
      SpringWaltraud GamblinWater Polo  20022005NY
      SpringBok McpeekSwimN 20162020NY
      SpringJerilyn ChaversWater Polo  20122015NY
      WestfieldSherril TackettSwimY 20082011YY
      WestfieldMaxima ConverseWater Polo  20072008YY
      WestfieldThea HartlSwimY 20092010YY
      WestfieldWilda VerdiWater Polo  20032006YY
      WestfieldLazaro FelchSwimY 20122013YY
      WestfieldChristi JamersonWater Polo  20072011YY

       

      Thinking on it, maybe I could create a helper conditional column that identifies if the school in the previous row is the same as the school in the current row, AND if the activity is Water Polo, and in that case it will fill in a Y or N as appropriate. The helper column could also look at if the NEXT column has the same school AND a "Swim" activity, to avoid scenarios like the above where Water Polo is listed first and it stays blank because it didn't have a Swim row to fill it in.

       

      (As a note, I'm going to work on making a formula to see if I can figure this out--Thank you again Jakinta for your response!)

      • Jakinta's avatar
        Jakinta
        Solution Sage
        let
            Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("lZRBb9pAEIX/yohzDsZAQo6BqG1IaFFAQSjKYbAn9oj1Ll2vaZ1f37WNgw22ox7Q4MO3b+fNm3197T0KYtm76s1RpwgL9naSUvu9RkMaFkoo+wHHn+v0r/PiOr23qxP8jEFCAu6Vxg/OgOUfjmzZnLjbJu6Roy1pEinc81ZgzI3osCjjGjpPNWMEvw5sTMd1+0Vxa+wqEQhzb0+4axJ03KIMcuiJIpVBMxVKmKhUoPTt5wRj2qIQR2pTIIU7fadGrpS01m4ozMTUu6lgULZ29KiKvfABJdxplKZNrz8qyk0NXIYWQYIJaz+mHGmUdQpjnTo98+CZAz//3yw6ro6yxO4OpFNYGgyCr/RG9dsa2tsLw0OE3Co5LMNXk5QYG/QYYWoBkm26bhECtz7PBUbWG5sDO08SW0yi1qkOy+FeuMwwQW0E/V/LC534JD07IYHerjUV/bL3Kmt3TJkQbRJVRPqLRJ3NaIbe70SkEqaaMFathtWDsdxrlkEuLSUZY+1W+z35AZ2W5+f5A3HM8ie7RmE0Jj58x2gr8i1sWdly+0b1AyZql68s7TpUj/1+QjPSnPcboo1n3PFOuOU+ZfyaYvPOJPx8zKTtIbCyk6L8qbl8L8blvM7hOf7lKPNLZvLU0fRNedL5EauQEH5kIWuUvq0+OFVuzcJHeCHtc4fsoJrsKv6EH6gVfCPhhU3CpWGDC3Iaao7tYszsfukiZN1NZ769/QM=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [School = _t, Player = _t, Sport = _t, #"School has Pool?" = _t, #"School Has Baseball Field?" = _t, #"Year Athlete Started on Team" = _t, #"Year Athlete Left Team" = _t]),
            #"Grouped Rows" = Table.Group(Source, {"School"}, {{"Gr", each _, type table }, {"Pool Info", each List.Max([#"School has Pool?"]), type nullable text}, {"Baseball Fielad Info", each List.Max([#"School Has Baseball Field?"]), type nullable text}}),
            #"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"School"}),
            #"Expanded Gr" = Table.ExpandTableColumn(#"Removed Columns", "Gr", Table.ColumnNames ( #"Removed Columns"[Gr]{0}))
        in
            #"Expanded Gr"
  • Anonymous's avatar
    Anonymous
    Not applicable

    This is true! Thank you again for the solution. I can see it has a lot of potential. I'm just not sure how much more specifics I can give on my situation due to confidentiality rules. I'm a bit unfamiliar with what technique you used for the most recent solution but I can tell it's powerful. If I wanted to learn more about it, what is it called? Is this a binary object?