| อาร์กิวเมนต์ | ชนิด | คำอธิบาย |
|---|---|---|
| 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 การคำนวณที่ลำดับชั้นหรือไม่ |
[ ] = อาร์กิวเมนต์ที่ไม่บังคับ
WINDOW ใช้ดึงช่วงของแถวภายในพาร์ทิชันตามลำดับที่กำหนด มันคืนค่าเป็นตาราง (ชุดแถว) ไม่ใช่ค่าเดียว ทำให้มันเหมาะสำหรับงานคำนวณแบบช่วงต่อเนื่อง เช่น rolling window, moving average, running total ตามลำดับเวลา หรือหาช่วงแถวรอบแถวปัจจุบัน
ที่เจ๋งของ WINDOW คือมันให้ control เต็มเหมี่ยมในการกำหนดช่วงแถว – ว่าจะเอาแถวก่อนหน้ากี่แถว แถวปัจจุบัน แถวหน้ากี่แถว และมันสมาร์ทพอในการ partition (แบ่งกลุ่ม) ตามเงื่อนไขที่ต้องการ ผมชอบนำ WINDOW มาใช้แทน EARLIER/OFFSET เมื่อต้องการ rolling calculation
ส่วนตัวผมแล้ว WINDOW ยังยากอยู่ เพราะ parameter พอสมควร และต้องเข้าใจเรื่อง relative vs absolute position ให้ดี แต่พอเข้าใจแล้ว มันจะฉลาดกว่า EARLIER มากในเรื่องการจัดการพาร์ทิชันและการเรียงลำดับ
เช่น เอาแถวก่อนหน้าและถัดไปเพื่อทำการสรุปแบบช่วง
เช่น สรุปยอดในช่วงแถวล่าสุดตามลำดับที่กำหนด
REL = relative position (offset) จาก current row, -2 หมายถึง 2 แถวก่อน, 0 หมายถึง แถวปัจจุบัน สำคัญคือต้องใช้ AVERAGEX (iterator) เพราะ WINDOW คืนตาราง ไม่ใช่ค่าเดียว
ABS = absolute position (ตำแหน่งแน่นอน), 1 = แถวแรก (1-indexed), 0 REL = แถวปัจจุบัน, PARTITIONBY(Sales[Year]) = แบ่งพาร์ทิชันแยกต่อปี
PARTITIONBY ทำให้ช่วงแถวหยุดไม่ไปไกลกว่าพาร์ทิชัน มันจะ reset เมื่อ CustomerID เปลี่ยน
KEEP = เก็บค่าว่าง ใช้เมื่อวันบางวันอาจไม่มีข้อมูล, SKIP = ข้ามค่าว่างเพื่อดึง record ถัดไป
WINDOW คืนค่าเป็นตาราง (ชุดแถว) ไม่ใช่ค่าเดียว จึงต้องนำไปสรุปต่อด้วย iterator เช่น SUMX, AVERAGEX, COUNTROWS, CONCATENATEX ถ้าต้อง scalar value นั่นคือส่วนหนึ่งของ DAX ที่สำคัญ – เข้าใจ row context vs filter context ผม
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 แบ่งพาร์ทิชัน (group) ก่อนสร้างช่วงแถว ช่วงแถวจะไม่ข้ามพาร์ทิชัน เช่น PARTITIONBY(Sales[CustomerID]) ช่วงแถวจะเริ่มใหม่สำหรับลูกค้าแต่ละคน ไม่ผสมลูกค้าคนที่แล้วกับคนใหม่
ที่จริง WINDOW จะตัด boundary โดยอัตโนมัติเมื่อชนพาร์ทิชัน มันจะส่งคืนตารางของแถวที่เหลือ ถ้าอยากรู้ตัวเลขจริงของแถวในช่วง ลองใช้ COUNTROWS() บนผลลัพธ์จาก WINDOW ดู
OrderBy กำหนดลำดับการเรียง ซึ่งเป็นหลักในการสร้างช่วงแถว ถ้าข้าม WINDOW จะ error หรือได้ผลลัพธ์ที่คาดไม่ได้ ลำดับที่ชัดเจนมีความสำคัญเท่า partition ผมแนะนำให้ระบุเสมอ
ฟังก์ชันที่ผู้เขียนโยงไว้กับ WINDOW จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง
INDEX ดึงแถวจากตำแหน่งที่ระบุ (Position) ภายในกลุ่มข้อมูลที่เรียงแล้ว โดยสามารถใช้ ORDERBY และ PARTITIONBY เพื่อควบคุมลำดับและการแบ่งกลุ่ม เหมาะสำหรับงาน window function เช่นดึงค่าอันดับที่ N
MATCHBY ระบุคอลัมน์ที่ใช้จับคู่และระบุแถวปัจจุบันใน window functions เพื่อให้การเลื่อน/เลือกตำแหน่งแถวทำงานถูกต้องเมื่อมีค่า ORDERBY ซ้ำ หรือเมื่อจำเป็นต้องกำหนดเอกลักษณ์ของแถว
ORDERBY ระบุลำดับการเรียงลำดับ (ASC/DESC) และการจัดการค่าว่าง สำหรับ window functions เช่น INDEX, OFFSET, WINDOW เพื่อกำหนดลำดับของแถวภายในกลุ่ม
PARTITIONBY ระบุคอลัมน์ที่ใช้แบ่งกลุ่มสำหรับ window functions เพื่อให้การเลื่อน/เลือกตำแหน่งเกิดขึ้น “ภายในกลุ่ม” ตามที่กำหนด มักใช้ร่วมกับ ORDERBY และ MATCHBY
AVERAGEX เป็น Iterator Function ที่วนลูปตารางทีละแถว คำนวณ Expression แล้วนำผลลัพธ์มาหาค่าเฉลี่ย เหมาะสำหรับกรณีที่ต้องการเฉลี่ยค่าที่คำนวณได้ เช่น ราคา×จำนวน หรือค่าเฉลี่ยของ Measure ในแต่ละกลุ่ม
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
EARLIER คืนค่าของคอลัมน์ใน Row Context ชั้นนอก (Outer Row Context) เพื่อให้คอลัมน์คำนวณสามารถอ้างอิงค่า “ของแถวปัจจุบัน” ระหว่างการวนซ้อน (เช่น FILTER ภายใน Calculated Column) ได้
MOVINGAVERAGE คำนวณค่าเฉลี่ยเคลื่อนที่ (moving average) บนแกนของ Visual Calculations ในตารางข้อมูล เหมาะสำหรับทำเส้นแนวโน้มที่เรียบขึ้นและลดความผันผวนของข้อมูล
ยังไม่มีบทความที่เกี่ยวข้องกับฟังก์ชันนี้
Comments
อีเมลของคุณจะไม่ถูกเผยแพร่