INDEX ดึงแถวจากตำแหน่งที่ระบุ (Position) ภายในกลุ่มข้อมูลที่เรียงแล้ว โดยสามารถใช้ ORDERBY และ PARTITIONBY เพื่อควบคุมลำดับและการแบ่งกลุ่ม เหมาะสำหรับงาน window function เช่นดึงค่าอันดับที่ N
=INDEX(<Position>, <Relation>[, <OrderBy>[, <PartitionBy>[, <MatchBy>[, <Blanks>[, <Reset>]]]]])
=INDEX(<Position>, <Relation>[, <OrderBy>[, <PartitionBy>[, <MatchBy>[, <Blanks>[, <Reset>]]]]])
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| Position | number | Yes | ตำแหน่งแถวที่ต้องการดึง (1-based integer) ค่าบวก = นับจากแรก (1 = แถวแรก) ค่าลบ = นับจากท้าย (-1 = แถวสุดท้าย) ถ้ากำหนด 0 หรือ BLANK() จะคืนตารางว่าง | |
| Relation | table | Optional | ALLSELECTED() ของคอลัมน์ OrderBy/PartitionBy | ตารางหรือ Table Expression ที่ต้องการดึงแถว ถ้าไม่ระบุจะใช้ ALLSELECTED() ของคอลัมน์ใน OrderBy และ PartitionBy |
| OrderBy | orderby | Optional | ไม่ระบุ | นิพจน์ ORDERBY() เพื่อกำหนดลำดับของแถว มีรูปแบบ ORDERBY(Column1, ASC/DESC, Column2, ASC/DESC, …) ถ้าไม่ระบุ Relation จะต้องระบุ OrderBy |
| PartitionBy | partitionby | Optional | ไม่ระบุ (ถือว่า 1 partition) | นิพจน์ PARTITIONBY() เพื่อแบ่งข้อมูลเป็นกลุ่ม INDEX จะดึงตำแหน่งภายในแต่ละกลุ่ม ถ้าไม่ระบุจะถือว่าข้อมูลทั้งหมดเป็น 1 กลุ่ม |
| MatchBy | matchby | Optional | ไม่ระบุ | นิพจน์ MATCHBY() สำหรับระบุคอลัมน์ที่ใช้ในการแมตช์เพื่อระบุแถวปัจจุบัน ใช้ในงาน Visual Calculations |
| Blanks | text | Optional | DEFAULT | วิธีจัดการค่า BLANK() ใน OrderBy: DEFAULT (เริ่มต้น), FIRST (ค่า BLANK มาแรก), LAST (ค่า BLANK มาท้าย) |
| Reset | text | Optional | ไม่ระบุ | ควบคุมการ Reset ที่ hierarchy level ต่างๆ ใช้ใน Visual Calculations เท่านั้น |
ใช้ INDEX(1, …) เพื่อดึงแถวแรกจากชุดวันที่ที่เลือก
ใช้ PARTITIONBY เพื่อดึงแถวตำแหน่ง N ในแต่ละกลุ่ม
เดือนแรก = VAR FirstMonth = INDEX( 1, ALLSELECTED(Date[MonthName]), ORDERBY(Date[MonthSequence], ASC) ) RETURN MINX(FirstMonth, Date[MonthName])เดือนแรก =
VAR FirstMonth =
INDEX(
1,
ALLSELECTED(Date[MonthName]),
ORDERBY(Date[MonthSequence], ASC)
)
RETURN
MINX(FirstMonth, Date[MonthName])
ได้ชื่อเดือนแรกในช่วงที่เลือก
ยอดขายเดือนสุดท้าย = VAR LastMonthSales = CALCULATE( [Total Sales], INDEX( -1, ORDERBY(Date[DateKey], DESC) ) ) RETURN LastMonthSalesยอดขายเดือนสุดท้าย =
VAR LastMonthSales =
CALCULATE(
[Total Sales],
INDEX(
-1,
ORDERBY(Date[DateKey], DESC)
)
)
RETURN
LastMonthSales
ได้ยอดขายรวมของเดือนสุดท้ายในลำดับ
ยอดขายอันดับ 1 ต่อหมวด = VAR Top1PerCategory = INDEX( 1, SUMMARIZECOLUMNS( Product[Category], Product[ProductID], "Sales", [Total Sales] ), ORDERBY([Sales], DES…ยอดขายอันดับ 1 ต่อหมวด =
VAR Top1PerCategory =
INDEX(
1,
SUMMARIZECOLUMNS(
Product[Category],
Product[ProductID],
"Sales", [Total Sales]
),
ORDERBY([Sales], DESC),
PARTITIONBY(Product[Category])
)
RETURN
MINX(Top1PerCategory, [Sales])
ได้ยอดขายสูงสุดในแต่ละหมวดสินค้า
เปรียบเทียบเดือนก่อน = VAR PreviousMonth = CALCULATE( [Total Sales], INDEX( -2, ORDERBY(Date[MonthSequence], DESC) ) ) VAR ThisMonth = [Total Sales] RETURN IF(I…เปรียบเทียบเดือนก่อน =
VAR PreviousMonth =
CALCULATE(
[Total Sales],
INDEX(
-2,
ORDERBY(Date[MonthSequence], DESC)
)
)
VAR ThisMonth = [Total Sales]
RETURN
IF(ISBLANK(PreviousMonth), BLANK(), ThisMonth - PreviousMonth)
ความแตกต่างยอดขายระหว่างเดือนนี้กับ 2 เดือนก่อน
INDEX คืนค่าเป็นตาราง (row table) ที่มี 1 แถว ถ้าต้องการค่าเดี่ยวให้ใช้ iterator เช่น MINX, MAXX, CONCATENATEX หรือ SELECTCOLUMNS เพื่อดึงคอลัมน์ที่ต้องการออกมา การใช้ INDEX ใน CALCULATE โดยตรงจะทำให้ filter context ของตาราง row นั้น ใช้ได้
INDEX ดึง “ตำแหน่งแบบสัมบูรณ์” (เช่นแถวที่ 3 หรือแถวสุดท้าย) ส่วน OFFSET ดึง “ตำแหน่งแบบสัมพัทธ์” (เช่น N แถวหลังจากแถวปัจจุบัน) INDEX ใช้ ORDERBY/PARTITIONBY ส่วน OFFSET ใช้ MATCHBY เพื่อระบุจุดเริ่มต้น นอกจากนี้ INDEX คืนตารางทั้งแถว ส่วน OFFSET อาจคืนค่าเดี่ยวได้
เมื่อ Position = 0, Position = BLANK(), หรือ Position เลยนอกช่วง (เช่น Position = 100 แต่มีแถวแค่ 50) INDEX จะคืนตารางว่าง ผมแนะนำให้ใช้ ISBLANK() หรือ COALESCE() เพื่อตรวจสอบและแสดงค่าเริ่มต้นแทน
ไม่จำเป็น ถ้าไม่ระบุ PARTITIONBY INDEX จะถือว่าข้อมูลทั้งหมดเป็น 1 partition ใช้ PARTITIONBY เมื่อต้องการดึงตำแหน่งภายในแต่ละกลุ่ม เช่น ผ่านแต่ละหมวดสินค้า/แต่ละอาคม/แต่ละลูกค้า
ไม่จำเป็น ถ้าไม่ระบุ ORDERBY INDEX จะใช้ลำดับเริ่มต้นของตารางทีเลือก แต่ส่วนมากจะระบุ ORDERBY เพื่อควบคุมลำดับให้แน่นอน ผมแนะนำให้ระบุ ORDERBY เสมอเพื่อหลีกเลี่ยงข้อผิดพลาด
ได้ แต่ต้องระวัง INDEX ใน Calculated Column ของตาราง Fact มักจะสูญเสีย Filter Context ที่ Row Level ดังนั้นจึงต้องใช้ ALLSELECTED() หรือ CALCULATETABLE() เพื่อสร้าง Relation ที่ถูกต้อง
INDEX เป็นฟังก์ชันที่ใช้ดึง “แถวที่ตำแหน่ง N” (เช่นแถวที่ 1, 2, 3 หรือแม้แต่แถวสุดท้าย) จากตารางหรือชุดข้อมูลที่กำหนด ลักษณะเด่นคือมันคืนตารางแถวเดี่ยว ไม่ใช่ค่าเดี่ยว ดังนั้นต้องใช้ iterator เช่น MINX, MAXX หรือ SELECTCOLUMNS เพื่อดึงค่าออกมา
ที่เจ๋งคือ INDEX ทำให้เราควบคุม “ลำดับ” ได้อย่างละเอียด ผ่าน ORDERBY และ PARTITIONBY ตัวอย่างเช่น อยากเปรียบเทียบยอดขายเดือนนี้กับเดือนที่แล้ว? ใช้ INDEX กับ ORDERBY ดึงช่วงเวลาก่อนหน้า แล้วใช้ CALCULATE เปรียบเทียบได้เลย หรืออยากหาผ่านแต่ละหมวดสินค้า? เพิ่ม PARTITIONBY ให้มันแบ่งกลุ่มก่อน
ส่วนตัวผม INDEX คือ Secret Weapon ของ Window Functions ครับ มันช่วยให้งาน Advanced Analytics เหมือน Ranking, Moving Average, YoY Comparison ทำได้ยุ่งเหยิง แถมเขียนง่ายกว่า Self-Join แบบเก่า ผมเลยชอบใช้ INDEX ตั้งแต่เคยรู้จักมัน 😎