Thep Excel

WINDOWดึงช่วงแถวภายในพาร์ทิชัน

WINDOW ดึงช่วงแถวภายในพาร์ทิชัน คืนค่าเป็นตาราง เหมาะกับการคำนวณแบบช่วง เช่น moving average, running sum, หรือ lead/lag analysis

fx
=WINDOW(<From>[, <FromType>], <To>[, <ToType>][, <Relation>][, <OrderBy>][, <Blanks>][, <PartitionBy>][, <MatchBy>][, <Reset>])

ความนิยม4/10
ความยาก6/10
ประโยชน์5/10

อัปเดต 13 December 2025

Syntax & Arguments

อาร์กิวเมนต์ ชนิด คำอธิบาย
From integer ตำแหน่งเริ่มของช่วง นิยมเป็นค่าลบ (แถวก่อนหน้า) เช่น -2 หมายถึง 2 แถวก่อนแถวปัจจุบัน
[FromType]ไม่บังคับ enumeration ชนิดการตีความ From: REL (relative, ค่าตั้งต้น) หรือ ABS (absolute) – REL = offset จากแถวปัจจุบัน, ABS = ตำแหน่งแน่นอนจากจุดเริ่มพาร์ทิชัน
To integer ตำแหน่งสิ้นสุดของช่วง มักเป็น 0 (แถวปัจจุบัน) หรือค่าบวก (แถวข้างหน้า)
[ToType]ไม่บังคับ enumeration ชนิดการตีความ To: REL หรือ ABS (ค่าตั้งต้น REL)
[Relation]ไม่บังคับ table ตาราง/ความสัมพันธ์ที่จะดึงช่วงแถวมา ถ้าไม่ระบุจะใช้ relation ของ OrderBy/PartitionBy
[OrderBy]ไม่บังคับ expression นิพจน์กำหนดลำดับการเรียงสำหรับการสร้างช่วงแถว เช่น ORDERBY(‘DimDate'[Date])
[Blanks]ไม่บังคับ enumeration วิธีจัดการค่าว่างในการเรียงลำดับ: SKIP (ข้ามค่าว่าง) หรือ KEEP (เก็บค่าว่าง)
[PartitionBy]ไม่บังคับ expression นิพจน์กำหนดการแบ่งพาร์ทิชัน เช่น PARTITIONBY(Sales[CustomerID]) – ช่วงแถวจะสร้างแยกในแต่ละพาร์ทิชัน
[MatchBy]ไม่บังคับ expression นิพจน์กำหนดการจับคู่แถว เมื่อหลายแถวมีค่าเดียวกันในลำดับ ช่วยกำหนดแถวไหนเป็นแถวปัจจุบัน
[Reset]ไม่บังคับ boolean ใช้ในการคำนวณภาพ (visual calculations) เท่านั้น กำหนดว่าจะ reset การคำนวณที่ลำดับชั้นหรือไม่

[ ] = อาร์กิวเมนต์ที่ไม่บังคับ

Additional Notes

WINDOW ใช้ดึงช่วงของแถวภายในพาร์ทิชันตามลำดับที่กำหนด มันคืนค่าเป็นตาราง (ชุดแถว) ไม่ใช่ค่าเดียว ทำให้มันเหมาะสำหรับงานคำนวณแบบช่วงต่อเนื่อง เช่น rolling window, moving average, running total ตามลำดับเวลา หรือหาช่วงแถวรอบแถวปัจจุบัน

ที่เจ๋งของ WINDOW คือมันให้ control เต็มเหมี่ยมในการกำหนดช่วงแถว – ว่าจะเอาแถวก่อนหน้ากี่แถว แถวปัจจุบัน แถวหน้ากี่แถว และมันสมาร์ทพอในการ partition (แบ่งกลุ่ม) ตามเงื่อนไขที่ต้องการ ผมชอบนำ WINDOW มาใช้แทน EARLIER/OFFSET เมื่อต้องการ rolling calculation

ส่วนตัวผมแล้ว WINDOW ยังยากอยู่ เพราะ parameter พอสมควร และต้องเข้าใจเรื่อง relative vs absolute position ให้ดี แต่พอเข้าใจแล้ว มันจะฉลาดกว่า EARLIER มากในเรื่องการจัดการพาร์ทิชันและการเรียงลำดับ

How it works

ดึงช่วงแถวรอบแถวปัจจุบัน

เช่น เอาแถวก่อนหน้าและถัดไปเพื่อทำการสรุปแบบช่วง

ทำการคำนวณแบบ rolling

เช่น สรุปยอดในช่วงแถวล่าสุดตามลำดับที่กำหนด

Examples

ตัวอย่างที่ 1: Moving Average 3 วัน (ช่วงแถวสัมพัทธ์)Moving Avg 3Day = AVERAGEX( WINDOW( -2, REL, 0, REL, ORDERBY(Sales[OrderDate]) ), Sales[Amount] ) — หรือ ใช้ VAR ให้ชัด: Moving Avg = VAR _window = WINDOW( -2,…

REL = relative position (offset) จาก current row, -2 หมายถึง 2 แถวก่อน, 0 หมายถึง แถวปัจจุบัน สำคัญคือต้องใช้ AVERAGEX (iterator) เพราะ WINDOW คืนตาราง ไม่ใช่ค่าเดียว

fx
Moving Avg 3Day =
AVERAGEX(
WINDOW(
-2, REL, 0, REL,
ORDERBY(Sales[OrderDate])
),
Sales[Amount]
)

— หรือ ใช้ VAR ให้ชัด:
Moving Avg =
VAR _window = WINDOW(
-2, REL, — เอา 2 แถวก่อน
0, REL, — ถึง แถวปัจจุบัน (รวม 3 แถว)
ORDERBY(Sales[OrderDate])
)
RETURN AVERAGEX(_window, Sales[Amount])

ผลลัพธ์ได้ค่าเฉลี่ยของ 3 วัน (วันก่อนหน้า 2 วัน + วันปัจจุบัน)
ตัวอย่างที่ 2: Running Sum (คะแนนรวมสะสม) ด้วยตำแหน่งสัมบูรณ์Running Sum Year = VAR _window = WINDOW( 1, ABS, — เริ่มจาก แถวแรกของปี (position 1) 0, REL, — ถึง แถวปัจจุบัน ALLSELECTED(Sales), ORDERBY(Sales[MonthNumber])…

ABS = absolute position (ตำแหน่งแน่นอน), 1 = แถวแรก (1-indexed), 0 REL = แถวปัจจุบัน, PARTITIONBY(Sales[Year]) = แบ่งพาร์ทิชันแยกต่อปี

fx
Running Sum Year =
VAR _window = WINDOW(
1, ABS, — เริ่มจาก แถวแรกของปี (position 1)
0, REL, — ถึง แถวปัจจุบัน
ALLSELECTED(Sales),
ORDERBY(Sales[MonthNumber]),
PARTITIONBY(Sales[Year])
)
RETURN SUMX(_window, Sales[Amount])

ผลลัพธ์ได้ยอดรวมสะสมตั้งแต่จุดเริ่มต้นของแต่ละปีจนถึงเดือนปัจจุบัน
ตัวอย่างที่ 3: ดึงแถวต่าง ๆ ภายในกลุ่มลูกค้า (Partition by Customer)Customer Window Rows = VAR _window = WINDOW( -3, REL, — 3 แถวก่อนหน้า 1, REL, — 1 แถวข้างหน้า ORDERBY(Sales[OrderDate]), PARTITIONBY(Sales[CustomerID]) ) RETU…

PARTITIONBY ทำให้ช่วงแถวหยุดไม่ไปไกลกว่าพาร์ทิชัน มันจะ reset เมื่อ CustomerID เปลี่ยน

fx
Customer Window Rows =
VAR _window = WINDOW(
-3, REL, — 3 แถวก่อนหน้า
1, REL, — 1 แถวข้างหน้า
ORDERBY(Sales[OrderDate]),
PARTITIONBY(Sales[CustomerID])
)
RETURN CONCATENATEX(
_window,
FORMAT(Sales[OrderDate], "dd/mm") & ": " & Sales[Amount],
" | "
)

ผลลัพธ์ได้ลำดับคำสั่งของลูกค้า 3 วันก่อน + วันปัจจุบัน + วันข้างหน้า ต่อวันปัจจุบัน
ตัวอย่างที่ 4: ดึงแถวเฉพาะจำนวนตามเงื่อนไข (KEEP blanks)Count Recent Orders = VAR _window = WINDOW( -7, REL, — ย้อนหลัง 7 วัน 0, REL, — ถึงวันปัจจุบัน ORDERBY(Sales[OrderDate]), KEEP — Keep blanks ที่อาจเกิด ) RET…

KEEP = เก็บค่าว่าง ใช้เมื่อวันบางวันอาจไม่มีข้อมูล, SKIP = ข้ามค่าว่างเพื่อดึง record ถัดไป

fx
Count Recent Orders =
VAR _window = WINDOW(
-7, REL, — ย้อนหลัง 7 วัน
0, REL, — ถึงวันปัจจุบัน
ORDERBY(Sales[OrderDate]),
KEEP — Keep blanks ที่อาจเกิด
)
RETURN COUNTROWS(_window)

ผลลัพธ์ได้จำนวนคำสั่งในช่วง 7 วัน (ถ้า SKIP จะข้ามวันที่ไม่มีคำสั่ง)

FAQs

WINDOW คืนค่าเป็นตัวเลขหรือตาราง?+

WINDOW คืนค่าเป็นตาราง (ชุดแถว) ไม่ใช่ค่าเดียว จึงต้องนำไปสรุปต่อด้วย iterator เช่น SUMX, AVERAGEX, COUNTROWS, CONCATENATEX ถ้าต้อง scalar value นั่นคือส่วนหนึ่งของ DAX ที่สำคัญ – เข้าใจ row context vs filter context ผม

REL กับ ABS ต่างกันอย่างไร พอให้ตัวอย่างหน่อยไหม?+

REL (relative) = offset จากแถวปัจจุบัน, -2 หมายถึง 2 แถวก่อน, 1 หมายถึง 1 แถวข้างหน้า, 0 = แถวปัจจุบัน

ABS (absolute) = ตำแหน่งแน่นอนจากจุดเริ่มต้นของพาร์ทิชัน, 1 = แถวแรก, 2 = แถวที่สอง, -1 = แถวสุดท้าย

กรณี partition มี 10 แถวและอยู่ที่แถวที่ 5:
WINDOW(-2, REL, 0, REL) = แถว 3 ถึง 5
WINDOW(1, ABS, 0, REL) = แถว 1 ถึง 5 (position 1 ไปถึง current row)

PARTITIONBY ทำอะไร?+

PARTITIONBY แบ่งพาร์ทิชัน (group) ก่อนสร้างช่วงแถว ช่วงแถวจะไม่ข้ามพาร์ทิชัน เช่น PARTITIONBY(Sales[CustomerID]) ช่วงแถวจะเริ่มใหม่สำหรับลูกค้าแต่ละคน ไม่ผสมลูกค้าคนที่แล้วกับคนใหม่

ผมจะรู้ว่า window boundaries ถูกตัดเพราะลงท้ายพาร์ทิชันได้ไง?+

ที่จริง WINDOW จะตัด boundary โดยอัตโนมัติเมื่อชนพาร์ทิชัน มันจะส่งคืนตารางของแถวที่เหลือ ถ้าอยากรู้ตัวเลขจริงของแถวในช่วง ลองใช้ COUNTROWS() บนผลลัพธ์จาก WINDOW ดู

ทำไม OrderBy ต้องระบุตลอด ไม่ได้ข้ามไหม?+

OrderBy กำหนดลำดับการเรียง ซึ่งเป็นหลักในการสร้างช่วงแถว ถ้าข้าม WINDOW จะ error หรือได้ผลลัพธ์ที่คาดไม่ได้ ลำดับที่ชัดเจนมีความสำคัญเท่า partition ผมแนะนำให้ระบุเสมอ

Resources & Related

ฟังก์ชันที่ผู้เขียนโยงไว้กับ WINDOW จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง

ฟังก์ชันนี้WINDOWFilter
Filter (4)
INDEX

INDEX ดึงแถวจากตำแหน่งที่ระบุ (Position) ภายในกลุ่มข้อมูลที่เรียงแล้ว โดยสามารถใช้ ORDERBY และ PARTITIONBY เพื่อควบคุมลำดับและการแบ่งกลุ่ม เหมาะสำหรับงาน window function เช่นดึงค่าอันดับที่ N

MATCHBY

MATCHBY ระบุคอลัมน์ที่ใช้จับคู่และระบุแถวปัจจุบันใน window functions เพื่อให้การเลื่อน/เลือกตำแหน่งแถวทำงานถูกต้องเมื่อมีค่า ORDERBY ซ้ำ หรือเมื่อจำเป็นต้องกำหนดเอกลักษณ์ของแถว

ORDERBY

ORDERBY ระบุลำดับการเรียงลำดับ (ASC/DESC) และการจัดการค่าว่าง สำหรับ window functions เช่น INDEX, OFFSET, WINDOW เพื่อกำหนดลำดับของแถวภายในกลุ่ม

PARTITIONBY

PARTITIONBY ระบุคอลัมน์ที่ใช้แบ่งกลุ่มสำหรับ window functions เพื่อให้การเลื่อน/เลือกตำแหน่งเกิดขึ้น “ภายในกลุ่ม” ตามที่กำหนด มักใช้ร่วมกับ ORDERBY และ MATCHBY

Aggregation (2)
AVERAGEX

AVERAGEX เป็น Iterator Function ที่วนลูปตารางทีละแถว คำนวณ Expression แล้วนำผลลัพธ์มาหาค่าเฉลี่ย เหมาะสำหรับกรณีที่ต้องการเฉลี่ยค่าที่คำนวณได้ เช่น ราคา×จำนวน หรือค่าเฉลี่ยของ Measure ในแต่ละกลุ่ม

SUMX

SUMX เป็น iterator function ที่ทรงพลังใน DAX ออกแบบมาเพื่อวนลูปทีละแถวในตารางที่กำหนด แล้วคำนวณ expression ที่ซับซ้อนสำหรับแต่ละแถวก่อนนำผลลัพธ์ทั้งหมดมารวมกัน ต่างจาก SUM ที่รวมเฉพาะค่าใน column เดียว SUMX สร้าง row context สำหรับแต่ละแถว ทำให้สามารถคำนวณ expression อย่าง Quantity × Price หรือใช้ RELATED ดึงข้อมูลข้ามตารางได้ มีกลไก context transition อัตโนมัติเมื่อเจอ measure ในนั้น เหมาะสำหรับการคำนวณซับซ้อนระดับแถวข้อมูล ประหยัดพื้นที่ model เพราะไม่ต้องสร้าง calculated column แต่ช้ากว่า SUM และไม่รองรับ DirectQuery mode ใน calculated columns หรือ RLS rules

Other (1)
EARLIER

EARLIER คืนค่าของคอลัมน์ใน Row Context ชั้นนอก (Outer Row Context) เพื่อให้คอลัมน์คำนวณสามารถอ้างอิงค่า “ของแถวปัจจุบัน” ระหว่างการวนซ้อน (เช่น FILTER ภายใน Calculated Column) ได้

Visual calculations (1)
MOVINGAVERAGE

MOVINGAVERAGE คำนวณค่าเฉลี่ยเคลื่อนที่ (moving average) บนแกนของ Visual Calculations ในตารางข้อมูล เหมาะสำหรับทำเส้นแนวโน้มที่เรียบขึ้นและลดความผันผวนของข้อมูล

Comments

อีเมลของคุณจะไม่ถูกเผยแพร่