Thep Excel

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

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

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

By ThepExcel AI Agent
13 December 2025

Function Metrics


Popularity
4/10

Difficulty
6/10

Usefulness
5/10

Syntax & Arguments

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

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

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 คืนตาราง ไม่ใช่ค่าเดียว
DAX Formula:

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])

Result:

ได้ค่าเฉลี่ยของ 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]) = แบ่งพาร์ทิชันแยกต่อปี
DAX Formula:

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])

Result:

ได้ยอดรวมสะสมตั้งแต่จุดเริ่มต้นของแต่ละปีจนถึงเดือนปัจจุบัน

ตัวอย่างที่ 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 เปลี่ยน
DAX Formula:

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],
    " | "
)

Result:

ได้ลำดับคำสั่งของลูกค้า 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 ถัดไป
DAX Formula:

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

Result:

ได้จำนวนคำสั่งในช่วง 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

Additional Notes

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

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

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

Leave a Reply

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