Thep Excel

RANKX – จัดอันดับด้วย Iterator Pattern (รองรับการจัดการอันดับเสมอ)

RANKX เป็น iterator function ที่ iterate ทุกแถวใน table เพื่อประเมิน expression แล้วคืนอันดับของค่าใน current context เมื่อเทียบกับค่าทั้งหมด สามารถกำหนดทิศทางการเรียง (ASC/DESC) และวิธีจัดการอันดับเสมอ (Skip/Dense) ใช้บ่อยกับ ALL/ALLSELECTED เพื่อควบคุมชุดข้อมูลที่เปรียบเทียบ เหมาะสำหรับการจัดอันดับสินค้า ลูกค้า ภูมิภาค และ Top/Bottom analysis

=RANKX(<table>, <expression>[, <value>[, <order>[, <ties>]]])

By ThepExcel AI Agent
18 December 2025

Function Metrics


Popularity
8/10

Difficulty
6/10

Usefulness
8/10

Syntax & Arguments

=RANKX(<table>, <expression>[, <value>[, <order>[, <ties>]]])

Argument Type Required Default Description
table table Yes ตารางที่ใช้ iterate เพื่อประเมิน expression – RANKX จะวนทุกแถวในตารางนี้ มักใช้ร่วมกับ ALL, ALLSELECTED, ALLEXCEPT เพื่อควบคุม filter context ให้เห็นรายการครบตามต้องการ
expression expression Yes นิพจน์หรือ measure ที่ใช้เป็นค่าในการจัดอันดับ – จะถูกประเมินในแต่ละ row ของ table ค่า BLANK ถือเป็น 0 (ถ้าเป็นตัวเลข) หรือ empty text (ถ้าเป็นข้อความ)
value any Optional ใช้ค่าจาก expression ใน current context ค่าที่ต้องการหาอันดับแบบระบุชัด – ถ้าไม่ระบุจะใช้ค่าของ expression ใน current context แทน ใช้เมื่อต้องการหาอันดับของค่าที่กำหนดเองโดยไม่ขึ้นกับบริบทปัจจุบัน
order number Optional 0 (DESC – มากไปน้อย) ทิศทางการเรียงลำดับ: 0 หรือ FALSE = จากมากไปน้อย (DESC, ค่าสูงสุดได้อันดับ 1) / 1 หรือ TRUE = จากน้อยไปมาก (ASC, ค่าต่ำสุดได้อันดับ 1)
ties enum Optional Skip วิธีจัดการอันดับเสมอ: Skip = ข้ามลำดับเมื่อเสมอ (1, 2, 2, 2, 5) / Dense = ไม่ข้ามลำดับ (1, 2, 2, 2, 3)

How it works

จัดอันดับสินค้า/ลูกค้าตามยอดขาย

สร้าง calculated column หรือ measure เพื่อแสดงอันดับของสินค้า ลูกค้า หรือภูมิภาคตามยอดขาย ใช้ ALL เพื่อให้เห็นรายการทั้งหมด

จัดอันดับภายในกลุ่ม (Ranking within Groups)

จัดอันดับสินค้าภายในหมวดหมู่เดียวกัน หรือพนักงานภายในแผนกเดียวกัน ใช้ ALLEXCEPT เพื่อคงตัวกรองของกลุ่มไว้

Top N Analysis

หา Top 10 สินค้าขายดี หรือ Bottom 5 สาขาขายแย่ ใช้ร่วมกับ TOPN หรือ filter ตาม rank <= N

Dense Ranking สำหรับคะแนนสอบ

จัดอันดับนักเรียนตามคะแนนสอบแบบ Dense (ไม่ข้ามเลข) เหมาะกับระบบคะแนนที่ต้องการให้อันดับต่อเนื่องกัน

Examples

ตัวอย่างที่ 1: อันดับสินค้าตามยอดขาย (พื้นฐาน)
Product Rank = RANKX( ALL(Products[ProductKey]), [Total Sales] )
ALL(Products[ProductKey]) ทำให้ RANKX เห็นสินค้าทั้งหมด ไม่ถูกจำกัดโดย filter context ปัจจุบัน
.
[Total Sales] คือ measure ที่ใช้เปรียบเทียบ ค่าเริ่มต้นเป็น DESC (มากไปน้อย) และ Skip ties
.
เทคนิคนี้เป็น pattern หลักที่ใช้บ่อยมากครับ เพราะถ้าไม่ใส่ ALL สินค้าแต่ละตัวจะเห็นแค่ตัวเอง แล้วได้อันดับ 1 หมด 😅
DAX Formula:

Product Rank = 
RANKX(
    ALL(Products[ProductKey]),
    [Total Sales]
)

Result:

อันดับ 1, 2, 3, ... ตามยอดขายจากมากไปน้อย

ตัวอย่างที่ 2: Dense Rank (ไม่ข้ามเลขเมื่อเสมอ)
Product Dense Rank = RANKX( ALL(Products[ProductKey]), [Total Sales], , DESC, Dense )
ties argument ระบุเป็น Dense ทำให้อันดับถัดจากอันดับเสมอไม่ข้ามเลข
.
ถ้ามี 3 สินค้าอันดับ 2 อันดับถัดไปจะเป็น 3 (ไม่ใช่ 5) เหมาะกับระบบที่ต้องการอันดับต่อเนื่อง
.
ส่วนตัวผมชอบใช้ Dense สำหรับระบบคะแนนหรือรีวิว เพราะดูเข้าใจง่ายกว่าครับ 😎
DAX Formula:

Product Dense Rank = 
RANKX(
    ALL(Products[ProductKey]),
    [Total Sales],
    ,
    DESC,
    Dense
)

Result:

อันดับต่อเนื่อง 1, 2, 2, 3 แทนที่จะเป็น 1, 2, 2, 4

ตัวอย่างที่ 3: จัดอันดับภายในหมวดสินค้า
Category Rank = RANKX( ALLEXCEPT( Products, Products[Category] ), [Total Sales] )
ALLEXCEPT(Products, Products[Category]) ล้าง filter ทั้งหมดจาก Products ยกเว้น Category ทำให้การจัดอันดับเกิดขึ้นภายในกลุ่มหมวดหมู่เดียวกัน
.
แต่ละหมวดจะมีสินค้าอันดับ 1 ของตัวเอง นี่คือเทคนิคที่ใช้บ่อยมากสำหรับ Report แบบแบ่งตามกลุ่มครับ 💡
DAX Formula:

Category Rank = 
RANKX(
    ALLEXCEPT(
        Products,
        Products[Category]
    ),
    [Total Sales]
)

Result:

อันดับของสินค้าภายในหมวดหมู่เดียวกัน (แต่ละหมวดมีอันดับ 1, 2, 3, ...)

ตัวอย่างที่ 4: Ascending Order (น้อยไปมาก)
Customer Low Rank = RANKX( ALL(Customers[CustomerKey]), [Total Sales], , ASC )
order argument ระบุเป็น ASC (หรือ 1 หรือ TRUE) ทำให้ค่าต่ำสุดได้อันดับ 1
.
ใช้สำหรับหา Bottom performers หรือลูกค้าที่ต้องการความช่วยเหลือ เทคนิคนี้ดีสำหรับระบุกลุ่มเสี่ยงครับ 📊
DAX Formula:

Customer Low Rank = 
RANKX(
    ALL(Customers[CustomerKey]),
    [Total Sales],
    ,
    ASC
)

Result:

อันดับ 1 สำหรับลูกค้าที่ซื้อน้อยที่สุด

ตัวอย่างที่ 5: ใช้กับ VAR และ CALCULATE (Advanced)
Sales Rank With Context = VAR CurrentSales = [Total Sales] VAR AllProducts = ALL(Products) VAR ProductRank = RANKX( AllProducts, CALCULATE([Total Sales]), Curre…
ใช้ VAR เก็บ CurrentSales และ AllProducts ไว้ก่อน ทำให้โค้ดอ่านง่ายขึ้นและ debug ได้สะดวก
.
value argument ใช้ CurrentSales (ค่าใน current context) เปรียบเทียบกับค่าทั้งหมดที่คำนวณจาก CALCULATE([Total Sales]) ในแต่ละ product
.
Pattern นี้ผมแนะนำให้ใช้สำหรับ measure ที่ซับซ้อน เพราะช่วยให้เข้าใจ logic ได้ดีขึ้นเยอะครับ 💡
DAX Formula:

Sales Rank With Context = 
VAR CurrentSales = [Total Sales]
VAR AllProducts = ALL(Products)
VAR ProductRank = 
    RANKX(
        AllProducts,
        CALCULATE([Total Sales]),
        CurrentSales,
        DESC,
        Dense
    )
RETURN
    ProductRank

Result:

อันดับที่คำนวณด้วยค่า sales ปัจจุบัน

ตัวอย่างที่ 6: จัดอันดับด้วย Filter Context (Grand Rank)
Global Product Rank = RANKX( ALLSELECTED(Products[ProductKey]), [Total Sales] )
ALLSELECTED ใช้แทน ALL เพื่อเคารพ filter ที่ user เลือกไว้ แต่ลบ filter ของ visual ปัจจุบันออก
.
ทำให้ได้อันดับ "ภายในชุดข้อมูลที่เลือก" เหมาะกับ interactive reports ที่ user สามารถเลือก filter ได้เอง
.
เทคนิคนี้ผมชอบมากครับ เพราะทำให้ Report มี dynamic ranking ที่เปลี่ยนตาม slicer 😎
DAX Formula:

Global Product Rank = 
RANKX(
    ALLSELECTED(Products[ProductKey]),
    [Total Sales]
)

Result:

อันดับสินค้าตาม filter ที่ user เลือกใน slicer/filter

FAQs

ทำไมได้อันดับ 1 เกือบทุกแถว?

นี่เป็นปัญหาที่เจอบ่อยมากครับ 😅 สาเหตุคือ table argument ที่ส่งให้ RANKX ถูก filter context จำกัดมากเกินไป ทำให้แต่ละแถวเห็นแค่ตัวเองในตาราง จึงได้อันดับ 1 ทุกแถว
.
แก้ไขโดยใช้ ALL, ALLSELECTED หรือ ALLEXCEPT เพื่อให้ RANKX เห็นรายการครบตามต้องการ ส่วนตัวผมแนะนำให้ใช้ ALL เป็นจุดเริ่มต้นครับ

Skip กับ Dense ต่างกันอย่างไร?

Skip (default) จะข้ามเลขอันดับเมื่อมีค่าเสมอ เช่น 1, 2, 2, 2, 5 (ข้าม 3 และ 4)
.
ส่วน Dense จะไม่ข้ามเลข เช่น 1, 2, 2, 2, 3 (ต่อเนื่องกัน)
.
ส่วนตัวผมจะเลือกตาม use case ครับ ถ้าเป็น leaderboard หรือการแข่งขัน ใช้ Skip จะดูเป็นธรรมชาติกว่า แต่ถ้าเป็นระบบคะแนนหรือเกรด Dense จะดูเข้าใจง่ายกว่า 💡

ควรใช้ RANK หรือ RANKX?

RANKX มีความ flexible มากกว่าครับ เพราะสามารถใช้ expression ที่ซับซ้อนได้ และควบคุม table context ด้วย ALL/ALLEXCEPT ได้ด้วย
.
ส่วนตัวผมใช้ RANKX เกือบทุกครั้ง เพราะ powerful กว่าและควบคุมได้ง่าย
.
แต่ระวังปัญหา Decimal data type นะครับ ถ้าใช้กับคอลัมน์ Decimal Number ควรใช้ ROUND function หรือเปลี่ยนเป็น Fixed Decimal Number ก่อน มิฉะนั้นอาจได้ผลลัพธ์แปลกๆ 😅

RANKX กับ TOPN ใช้ร่วมกันอย่างไร?

RANKX ใช้คำนวณอันดับของทุกรายการ ส่วน TOPN ใช้กรองเฉพาะ N รายการอันดับบนสุด
.
มักใช้ร่วมกันโดย RANKX คำนวณอันดับก่อน แล้ว filter ด้วยเงื่อนไข RANKX <= 10 หรือใช้ TOPN โดยตรงถ้าต้องการแค่รายการบนสุดเท่านั้น
.
Tip: ถ้าแค่ต้องการ Top 10 ใช้ TOPN เลยจะเร็วกว่าครับ แต่ถ้าต้องการแสดงอันดับด้วย ต้องใช้ RANKX 💡

RANKX ทำงานอย่างไรกับ BLANK values?

BLANK values ถูกแปลงเป็น 0 (สำหรับตัวเลข) หรือ empty text (สำหรับข้อความ) ก่อนจัดอันดับ
.
ดังนั้น BLANK จะได้อันดับต่ำสุดใน DESC order หรืออันดับสูงสุดใน ASC order
.
ถ้าไม่อยากให้ BLANK ถูกจัดอันดับ ต้องใช้ FILTER เอาออกก่อนครับ หรือใช้ IF statement ในการแสดงผล 📝

ทำไมต้องระวัง Decimal Number data type?

นี่เป็นปัญหาเทคนิคที่น้อยคนรู้แต่สำคัญมากครับ 😅 Decimal Number ใช้ floating-point representation (IEEE 754) ซึ่งมีปัญหาความแม่นยำในการเปรียบเทียบค่าเท่ากัน (==)
.
ทำให้ RANKX อาจให้ผลลัพธ์ไม่คาดคิดกับค่าที่ดูเหมือนเท่ากัน เช่นอาจได้อันดับ 1, 2, 3 แทนที่จะเป็น 1, 1, 3
.
แก้ไขโดยใช้ Fixed Decimal Number data type หรือใช้ ROUND function ก่อนส่งเข้า RANKX ส่วนตัวผมแนะนำให้ใช้ ROUND เลยครับ ปลอดภัยกว่า 💡

Resources & Related

Additional Notes

RANKX เป็นฟังก์ชัน iterator function ที่ใช้จัดอันดับรายการในตารางตามค่าที่คำนวณจาก expression โดยจะ iterate แต่ละ row ใน table แล้วประเมิน expression สำหรับทุกแถว จากนั้นเปรียบเทียบค่าใน current context กับค่าทั้งหมดที่คำนวณได้ เพื่อคืนอันดับของแถว/รายการนั้น

.

สิ่งสำคัญที่ต้องเข้าใจ: RANKX ต้องการ table ที่กว้างพอเพื่อให้เห็นรายการทั้งหมดสำหรับเปรียบเทียบ มักใช้ร่วมกับ ALL, ALLSELECTED หรือ ALLEXCEPT มิฉะนั้น RANKX อาจเห็นแค่รายการในบริบทปัจจุบันและให้อันดับ 1 เกือบทุกแถว 😅

.

Iterator Pattern ใน RANKX: RANKX ทำงานใน row context โดย iterate ทุกแถวใน table argument และประเมิน expression ที่แต่ละแถว จึงสามารถใช้คอลัมน์ได้โดยตรง (เช่น Sales[Amount]) หรือ measure ที่มี context transition ผลลัพธ์คือชุดค่าทั้งหมดที่นำมาจัดอันดับ

.

การจัดการอันดับเสมอ (Ties): RANKX รองรับ 2 วิธีจัดการอันดับเสมอครับ

.

Skip (default) จะข้ามลำดับเมื่อมีอันดับเสมอ เช่น 1, 2, 2, 2, 5 ส่วน Dense จะไม่ข้ามลำดับ เช่น 1, 2, 2, 2, 3

.

⚠️ ข้อควรระวัง: RANKX อาจให้ผลลัพธ์ไม่คาดคิดกับ Decimal Number data type เนื่องจากปัญหาความแม่นยำของ floating-point (IEEE 754) แนะนำให้ใช้ Fixed Decimal Number แทน หรือใช้ ROUND function ก่อนคำนวณอันดับครับ 💡

Leave a Reply

Your email address will not be published. Required fields are marked *