Học Power BI Qua Challenges

Học PBI Qua Challenge: Matrix Đổi Trục Thời Gian & Lọc “Last N” Động

Email Yêu Cầu Từ Leader

Team đang có 3 matrix riêng lẻ:

  • Matrix theo Fiscal Week → chỉ hiển thị Last 5 Weeks
  • Matrix theo Fiscal Period → chỉ hiển thị Last 2 Periods
  • Matrix theo Date → chỉ hiển thị Last 30 Days

Anh muốn gộp lại thành 1 matrix duy nhất và dùng slicer để người dùng chọn trục thời gian. Yêu cầu:

  • Có slicer chọn Time grain: Date / FiscalWeek / FiscalPeriod.
  • Có slicer chọn N (Last N) và danh sách N phải đổi theo grain:
    • Date: cho phép 1 – 60
    • Week: cho phép 1 – 12
    • Period: cho phép 1 – 6
  • Có label động trên report: “Showing: Last N days/weeks/periods”
  • Outout anh mong muốn

Bước 1: Relationship

  • DimDate[DateKey] (1) → FactGoodsIssue[DateKey] (*)
  • DimCustomer[CustomerKey] (1) → FactGoodsIssue[CustomerKey] (*)
  • DimStatus[StatusKey] (1) → FactGoodsIssue[StatusKey] (*)

Bước 2: Sort để Week/Period hiển thị đúng thứ tự

  • Chọn DimDate[FiscalWeek] → Sort by column → DimDate[WeekIndex]
  • DimDate[FiscalPeriod] → Sort by column → DimDate[PeriodIndex]

Bước 3:

Goods Issue =
SUM ( FactGoodsIssue[Goods Issue] )

Bước 4: Tạo Field Parameter để switch cột

  • 4.1. Vào Modeling → New parameter → Fields
  • 4.2. Chọn 3 field từ DimDate (nhớ chọn từ DimDate, không chọn từ Fact):
    • DimDate[Date]
    • DimDate[FiscalWeek]
    • DimDate[FiscalPeriod]
  • 4.3. Đặt tên: Time Axis
  • 4.4. Tick “Add slicer to this page”

Field Parameter hoạt động như thế nào?

Time Axis = {                                                               
      ("Date", NAMEOF('DimDate'[Date]), 0),                                   
       ▲         ▲                       ▲                                    
       │         │                       │                                    
       │         │                       └── Thứ tự (Order)                   
       │         │                                                            
       │         └── NAMEOF(): Lấy tên đầy đủ của field                       
       │             (để Power BI biết tham chiếu đến đâu)                    
       │                                                                      
       └── Label hiển thị cho user                                                                                                                        
  } 

Bước 5: Tạo table GrainConfig để định nghĩa default & giới hạn N theo grain

Vào Modeling → New table

GrainConfig = 
DATATABLE( -- Tạo bảng "cứng" trong model, chỉ dùng cho bảng TĨNH, ít dòng
-- Phù hợp cho: config tables, mapping tables, lookup tables
    "Grain", STRING, -- Khai báo cột 1: tên + kiểu dữ liệu
    "GrainOrder", INTEGER,
    "WindowLabel", STRING,
    "WindowSize", INTEGER, -- Default khi user chưa chọn N
    "MaxN", INTEGER, -- Giới hạn danh sách N hợp lệ theo grain
{ -- Bắt đầu dữ liệu (các dòng)
    {"Date",        0, "Last 30 Days",     30, 60}, -- Dòng 1
    {"FiscalWeek",  1, "Last 5 Weeks",      5, 12},
    {"FiscalPeriod",2, "Last 2 Periods",    2, 6}
})

Tại sao cần bảng GrainConfig?

Bước 6: Tạo table N Options để slicer N tự đổi theo grain

Vào Modeling → New table

N Options =                                                                 
  GENERATE(                       -- Hàm "nhân" 2 bảng với nhau              
      GrainConfig,                -- Bảng 1: lấy từ GrainConfig (3 dòng)     
      SELECTCOLUMNS(                                                          
          GENERATESERIES(         -- Tạo dãy số từ 1 đến MaxN                
              1,                  -- Bắt đầu từ 1                            
              GrainConfig[MaxN],  -- Kết thúc ở MaxN (60, 12, hoặc 6)        
              1                   -- Bước nhảy = 1                           
          ),                                                                  
          "N", [Value]            -- Đổi tên cột thành "N"                   
      )                                                                       
  )          

Tại sao cần bảng N Options?

  • Khi user chọn Date → Slicer N hiện: 1, 2, 3, … 60
  • Khi user chọn Week → Slicer N hiện: 1, 2, 3, … 12
  • Khi user chọn Period → Slicer N hiện: 1, 2, 3, … 6
  • Nếu dùng 1 bảng cố định [1-60] → Period vẫn hiện 60 giá trị (sai UX!)
  • Giải pháp: Tạo table N Options chứa tất cả các giá trị của N
    • Mỗi dòng = 1 cặp (Grain, N)
    • Dùng relationship để filter: chọn grain nào → chỉ hiện N của grain đó

Kiến thức DAX: Hàm GENERATE() + GENERATESERIES() trực quan

KHI user chọn → Slicer N sẽ tự lọc theo relationship

Tạo relationship để slicer N tự lọc theo grain

  • Time Axis'[Time Axis Order] → GrainConfig[GrainOrder]
  • GrainConfig[GrainOrder] → N Options[GrainOrder]

Bước 7: DAX “Last N”

-- Measure lấy N
Selected N = 
VAR NFromSlicer = SELECTEDVALUE('N Options'[N])
VAR DefaultN = MAX(GrainConfig[WindowSize]) 
RETURN COALESCE(NFromSlicer, DefaultN)
Goods Issue (Last N Visible) = 
VAR N = [Selected N]

VAR MaxDate =
    CALCULATE ( MAX ( DimDate[Date] ), ALLSELECTED ( DimDate ) )
VAR MaxWeekIndex =
    CALCULATE ( MAX ( DimDate[WeekIndex] ), ALLSELECTED ( DimDate ) )
VAR MaxPeriodIndex =
    CALCULATE ( MAX ( DimDate[PeriodIndex] ), ALLSELECTED ( DimDate ) )

VAR InWindow =
    SWITCH (
        TRUE (),

        ISINSCOPE ( DimDate[Date] ),
            MAX ( DimDate[Date] ) >= MaxDate - ( N - 1 ),

        ISINSCOPE ( DimDate[FiscalWeek] ),
            MAX ( DimDate[WeekIndex] ) >= MaxWeekIndex - ( N - 1 ),

        ISINSCOPE ( DimDate[FiscalPeriod] ),
            MAX ( DimDate[PeriodIndex] ) >= MaxPeriodIndex - ( N - 1 ),

        TRUE()
    )
RETURN
IF ( InWindow, [Goods Issue], BLANK() )

BLANK() làm matrix tự ẩn cột

Tại sao dùng ISINSCOPE thay vì SELECTEDVALUE?

Vấn đề: Làm sao biết user đang xem theo Date, Week, hay Period?

VAR Grain = SELECTEDVALUE(‘Time Axis'[Time Axis]) -> Đọc từ slicer (LỖI) -> Vì: Field Parameter là “composite” (chứa nhiều field)

Dùng ISINSCOPE

  • ISINSCOPE(DimDate[Date]) = TRUE nếu Date đang được GROUP BY
  • ISINSCOPE(DimDate[FiscalWeek]) = TRUE nếu Week đang được GROUP BY
  • → Không đọc từ slicer, mà kiểm tra Matrix đang group theo field nào -> Không bị composite key issues

Kiến thức DAX: Hàm ISINSCOPE() trực quan

Kiến thức DAX: Hàm COALESCE() và SWITCH(TRUE())

COALESCE(value1, value2, …) = Trả giá trị đầu tiên KHÔNG phải BLANK

    Selected N =                                                           
    VAR NFromSlicer = SELECTEDVALUE('N Options'[N])  ← Có thể BLANK       
    VAR DefaultN = MAX(GrainConfig[WindowSize])      ← Fallback          
    RETURN COALESCE(NFromSlicer, DefaultN)                               
                                                                        
    → Nếu user không chọn N → dùng DefaultN (30, 5, hoặc 2)

    SWITCH(TRUE(), …) = Pattern “if – elseif – else” trong DAX

    SWITCH(                                                               
          TRUE(),                         ← Kiểm tra điều kiện nào TRUE     
          ISINSCOPE(DimDate[Date]), ...,  ← Nếu Date → chạy logic Date     
          ISINSCOPE(DimDate[Week]), ...,  ← Nếu Week → chạy logic Week       
          TRUE()                          ← Default (else)                   
      )                                                                     
                                                                            
    Kiểm tra từ trên xuống, dừng ở điều kiện TRUE đầu tiên  

    Bước 8: Label “Showing: Last N days/weeks/periods”

     Label - Window =                                                            
      VAR Grain = MAX(GrainConfig[Grain])    -- Lấy grain đang được chọn           
      VAR N = [Selected N]                   -- Lấy N từ slicer/default            
      VAR Unit =                                                                  
          SWITCH(                                                                 
              Grain,                                                              
              "Date", "days",                -- Date → hiện "days"                 
              "FiscalWeek", "weeks",         -- Week → hiện "weeks"                
              "FiscalPeriod", "periods",     -- Period → hiện "periods"            
              "days"                         -- Default                            
          )                                                                       
      RETURN                                                                      
      "Showing: Last " & N & " " & Unit      -- Ghép chuỗi                                                                                                                                                                  

    Nếu bạn thích vừa học kiến thức vừa thực chiến qua Challenges như thế này thì có thể đăng ký khóa học Power BI Mastery Thực Chiến . Để đăng ký khóa học, bạn có thể inbox mình Tại Đây.

    Leave a Comment