Thep Excel

GENERATE – วนแถวตารางแรก สร้างตารางเพิ่มเติมในแต่ละรอบ แล้วรวมผลทั้งหมด

GENERATE วนทีละแถวใน Table1 แล้วประเมิน Table2 ในบริบทของแถวนั้น (row context) จากนั้นรวมผลทั้งหมดเป็นตารางเดียว ถ้า Table2 ว่างเปล่าในรอบไหน แถวนั้นจาก Table1 จะถูกตัดออก (ต่างจาก GENERATEALL)

=GENERATE(<Table1>, <Table2>)

By ThepExcel AI Agent
13 December 2025

Function Metrics


Popularity
5/10

Difficulty
6/10

Usefulness
5/10

Syntax & Arguments

=GENERATE(<Table1>, <Table2>)

Argument Type Required Default Description
Table1 table Yes ตารางหลักที่ใช้วนทีละแถว ทุกค่าในแถวปัจจุบันจะกลายเป็น row context เพื่อใช้อ้างอิงใน Table2
Table2 table Yes นิพจน์ตารางที่ถูกประเมินในบริบท (row context) ของแต่ละแถวใน Table1 แล้วนำผลมารวมกัน ถ้าผลว่างเปล่าในรอบไหน แถวจากนั้นจาก Table1 จะถูกตัดออก

How it works

ขยายตารางแม่ให้มีแถวย่อยตามเงื่อนไข

เช่น สร้างแถวรายละเอียดตามแต่ละรายการในตารางหลัก

สร้างตารางจากการวนแถวและคืนตารางย่อย

เหมาะกับการสร้างตารางคำนวณที่ต้องประกอบจากหลายส่วน

Examples

ตัวอย่างที่ 1: ขยายช่วงวันเป็นแถวเดี่ยว
DateList = GENERATE( VALUES(DateRange[StartDate]), ADDCOLUMNS( GENERATESERIES([Value], [Value] + 10), "DayOffset", [Value] ) )
GENERATE วนแต่ละ StartDate แล้วสร้าง 11 แถว (offset 0–10) ผลลัพธ์คือ N×11 แถว
DAX Formula:

DateList =
GENERATE(
    VALUES(DateRange[StartDate]),
    ADDCOLUMNS(
        GENERATESERIES([Value], [Value] + 10),
        "DayOffset", [Value]
    )
)

Result:

ตารางที่มี StartDate ของแต่ละแถว พร้อมคอลัมน์ DayOffset 0–10 ต่อแต่ละ StartDate

ตัวอย่างที่ 2: ดึงแถวลูกต่อแต่ละหมวดหมู่ (Unpivot Pattern)
CategoryWithProducts = GENERATE( VALUES(Product[Category]), FILTER( Product, Product[Category] = EARLIER(Product[Category]) ) )
วนหมวดหมู่แต่ละหมวด แล้วดึงผลิตภัณฑ์ที่ตรงกับหมวดนั้น EARLIER() ใช้อ้างอิงค่า row context
DAX Formula:

CategoryWithProducts =
GENERATE(
    VALUES(Product[Category]),
    FILTER(
        Product,
        Product[Category] = EARLIER(Product[Category])
    )
)

Result:

ตารางแสดงแต่ละหมวดหมู่พร้อมรายชื่อผลิตภัณฑ์ของหมวดนั้น

ตัวอย่างที่ 3: เปรียบเทียบ GENERATE กับ GENERATEALL
Without Empty = GENERATE(...) With Empty = GENERATEALL(...)
GENERATE ≈ SQL CROSS APPLY (ลบแถวที่ไม่มีข้อมูลในเงื่อนไข) | GENERATEALL ≈ SQL OUTER APPLY (คงไว้)
DAX Formula:

Without Empty = GENERATE(...)
With Empty = GENERATEALL(...)

Result:

ถ้า Table2 คืนค่าว่าง: GENERATE ตัดแถวออก | GENERATEALL เก็บแถว (NULL ในคอลัมน์ Table2)

FAQs

ทำไม EARLIER() ถึงสำคัญใน GENERATE?

เพราะว่า GENERATE ส่งผ่าน row context จากแต่ละแถวของ Table1 ลงไปใน Table2 ถ้าคุณใช้ [Column] โดยตรง DAX อาจสับสน ว่าหมายถึง Table1 หรือ Table2 ดังนั้น EARLIER([Column]) ช่วยบอก “หมายถึงค่าบริบทนอก (outer context) นั่น”

เมื่อไหร่ใช้ GENERATE เมื่อไหร่ใช้ CROSSJOIN?

CROSSJOIN = ผลคูณคาร์ทีเซียน (ทั้งหมด ×ทั้งหมด) | GENERATE = คูณเฉพาะส่วนที่ Table2 คืนมา ให้บริบทจาก Table1 จึงยืดหยุ่นกว่า

GENERATE ใช้ได้กับ DirectQuery ไหม?

ใช้ได้บ้างนี่: ✓ Measures | ✓ Visual calculations | ✗ Calculated columns / RLS rules ใน DirectQuery mode

ประสิทธิภาพของ GENERATE เป็นไงบ้าง?

ระวังปริมาณแถว: ถ้า Table1 มี 1,000 แถว และ Table2 ได้ 100 แถวต่อแถว ผลลัพธ์คือ 100,000 แถว อย่าลืมชั่งปริมาณ

Resources & Related

Additional Notes

GENERATE เป็นฟังก์ชันแบบ table iterator ที่ใช้ row context: มันวนทีละแถวใน Table1 แล้วประเมิน Table2 ในบริบทของแถวนั้น แล้วรวมผลลัพธ์ทั้งหมด

จุดสำคัญ: Row Context คืออะไร? ตอนที่ GENERATE วนแถวที่ 1 ของ Table1 ค่าทั้งหมดของแถวนั้นก็จะ “เข้าสู่บริบท” ทำให้ Table2 สามารถอ้างอิง [Column] ของแถวนั้นได้โดยตรง เช่น

GENERATE(
DateRange,
ADDCOLUMNS(
GENERATESERIES(EARLIER([StartDate]), EARLIER([EndDate])),
“Day”, [Value]
)
)

ในตัวอย่างนี้ EARLIER([StartDate]) เป็นการอ้างอิงค่าแถวปัจจุบันของ DateRange โดยหลีกเลี่ยง context ของ GENERATESERIES

ส่วนตัวผม GENERATE เป็นเหมือน SQL CROSS APPLY กล่าวคือ “วนแต่ละแถว แล้วเฉพาะค่ายอดนิยมต่อแถวนั้น” เหมาะมากเมื่องานต้อง unpivot หรือขยายแถวตามเงื่อนไข พลังจริง ๆ เลย

Leave a Reply

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