Thep Excel

GENERATEALLสร้าง Cartesian Product แบบคงแถวว่าง

GENERATEALL วนแถวของตาราง 1 แล้วสร้าง Cartesian product กับผลลัพธ์ของตาราง 2 โดยคงแถวที่ไม่มีข้อมูลย่อย ต่างจาก GENERATE ตรงที่ไม่ตัดแถวหลักออก

fx
=GENERATEALL(<table1>, <table2>)

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

อัปเดต 13 December 2025

Syntax & Arguments

อาร์กิวเมนต์ ชนิด คำอธิบาย
table1 table ตารางหลักที่จะวนแถวทีละแถว ต้องเป็นนิพจน์ DAX ที่คืนตาราง
table2 table นิพจน์ตารางที่ประเมินแยกต่อแถวของ table1 ใน row context ของแถวปัจจุบัน อาจคืนผลว่าง (ไม่มีแถว) แต่จะถูกเก็บไว้ในผลลัพธ์ final

Additional Notes

GENERATEALL คือฟังก์ชันสำคัญในเมื่อต้องการรวมตารางสองตารางแบบ outer apply ทำงานโดยวนแถวของ Table1 ทีละแถว แล้วประเมิน Table2 ในบริบทของแถวนั้น สร้าง Cartesian product จากผลลัพธ์ และสำคัญตรงนี้ – ถ้า Table2 ให้ผลว่างสำหรับแถวใดแถวหนึ่ง แถวนั้นจะถูกเก็บไว้ในผลลัพธ์พร้อม null values สำหรับคอลัมน์ของ Table2

ที่เจ๋งคือการทำงานแบบ outer apply นี้มีประโยชน์มากสำหรับการหา records ที่ไม่มี match ในตารางที่สอง เช่น สินค้าที่ไม่มีรายการขาย หรือลูกค้าที่ไม่มีธุรกรรม ถ้าใช้ GENERATE ธรรมดา มันจะตัดแถวเหล่านั้นออกไป แต่ GENERATEALL เก็บไว้เพื่อให้คุณเห็นความครอบคลุมที่แท้จริง

ส่วนตัวผมใช้ GENERATEALL เวลาต้องการ audit หรือ gap analysis – หาว่าสินค้าไหนขายไม่ออก ลูกค้าไหนไม่ซื้อ หรือคู่ region-product ไหนไม่มีข้อมูล ทำให้รายงานครบถ้วนและเห็นจุดที่ควรปรับปรุง

How it works

คงแถวของตารางหลักแม้ตารางย่อยไม่มีแถว

เหมาะกับงานตรวจสอบ/การวิเคราะห์ที่ไม่อยากให้แถวหายไปเมื่อไม่มีข้อมูลย่อย

สร้างตารางขยายเพื่อทำรายงานความครอบคลุม

เช่น ตรวจว่ารายการไหนไม่มีข้อมูลย่อย

Examples

ตัวอย่างที่ 1: คงสินค้าที่ไม่มีรายการขายProduct Sales Coverage = GENERATEALL( Products, FILTER(Sales, Sales[ProductID] = Products[ProductID]) )

ใช้ GENERATEALL กับ FILTER เพื่อขยายแต่ละสินค้าไปกับรายการขายที่ตรงกัน ถ้าสินค้าไม่มีขายเลย GENERATEALL ยังคงให้ผลลัพธ์ 1 แถวของสินค้านั้นโดยมี null columns สำหรับ Sales ช่วยให้เห็นสินค้าใดขายไม่ออก

fx
Product Sales Coverage =
GENERATEALL(
Products,
FILTER(Sales, Sales[ProductID] = Products[ProductID])
)

ผลลัพธ์ตารางที่มีสินค้าทั้งหมด รวมสินค้าที่ไม่มี Sales record
ตัวอย่างที่ 2: เปรียบเทียบกับ GENERATEGENERATE Example = GENERATE( Products, FILTER(Sales, Sales[ProductID] = Products[ProductID]) )

GENERATE และ GENERATEALL มี syntax เหมือนกัน แต่ถ้า FILTER ไม่มีแถวสำหรับสินค้าใด GENERATE จะไม่รวมสินค้านั้นในผลลัพธ์ ส่วน GENERATEALL จะรวมไว้ คำเลือกขึ้นอยู่ว่าต้องการเห็นแถวว่างหรือไม่

fx
GENERATE Example =
GENERATE(
Products,
FILTER(Sales, Sales[ProductID] = Products[ProductID])
)

ผลลัพธ์ตารางเฉพาะสินค้าที่มี Sales record (ตัดสินค้าที่ไม่มีขายออก)
ตัวอย่างที่ 3: ขยาย Date Range แบบเก็บช่วงว่างDate Range Expansion = GENERATEALL( DISTINCT(Orders[OrderDate]), FILTER( CALENDAR([OrderDate], DATE(2025, 12, 31)), [Date] >= Orders[OrderDate] ) )

สร้างชุดวันที่สำหรับแต่ละ order date ถึง 31 Dec 2025 แม้บางวันไม่มีข้อมูลธุรกรรม GENERATEALL เก็บไว้ ใช้สำหรับสร้างรายงาน timeline หรือ Gantt chart

fx
Date Range Expansion =
GENERATEALL(
DISTINCT(Orders[OrderDate]),
FILTER(
CALENDAR([OrderDate], DATE(2025, 12, 31)),
[Date] >= Orders[OrderDate]
)
)

ผลลัพธ์ตารางขยายที่มีทุกวันตั้งแต่ Order Date ไป ปลายปี แม้ไม่มีรายการ
ตัวอย่างที่ 4: ใช้ VAR เพื่อ debug ผลลัพธ์ไม่มีข้อมูลProduct Analysis = VAR ProductsSummary = ADDCOLUMNS( Products, "Sales Count", COUNTROWS(FILTER(Sales, Sales[ProductID] = Products[ProductID])) ) RETURN GENERATE…

ขั้นแรก สร้าง ProductsSummary ด้วย ADDCOLUMNS บวกจำนวนขายต่อสินค้า แล้ว GENERATEALL ใช้ IF เพื่อตัดสินใจว่าประเมิน FILTER หรือ BLANK ตามจำนวนขาย ตัวอย่างนี้แสดงการ combine logic ซับซ้อนในลำดับชั้น table generation

fx
Product Analysis =
VAR ProductsSummary = ADDCOLUMNS(
Products,
"Sales Count", COUNTROWS(FILTER(Sales, Sales[ProductID] = Products[ProductID]))
)
RETURN
GENERATEALL(
ProductsSummary,
IF(
[Sales Count] > 0,
FILTER(Sales, Sales[ProductID] = Products[ProductID]),
BLANK()
)
)

ผลลัพธ์ตารางขยายที่มีผลลัพธ์เฉพาะสินค้าที่มีขาย แต่คงโครงสร้างเดียว

FAQs

GENERATEALL ต่างจาก GENERATE เมื่อไรถึงเห็นผลชัด?+

เวลา table2 ให้ผลว่าง (ไม่มีแถว) สำหรับบางแถวของ table1 GENERATE ตัดแถวเหล่านั้นออก แต่ GENERATEALL เก็บไว้พร้อม null values ที่เหมาะสำหรับการตรวจสอบครบถ้วน

GENERATEALL จะช่วยตรวจหา missing values ได้ไหม?+

ได้ ผม มักใช้ GENERATEALL รวมกับ COUNTROWS หรือ COALESCE เพื่อตรวจว่าแถวไหนไม่มีข้อมูลจาก table2 ลองแล้วจะเห็นความ valuable ในการ audit

GENERATEALL vs CROSSJOIN ต่างกันอย่างไร?+

CROSSJOIN สร้าง Cartesian product ธรรมชาติ (ทุกคู่) GENERATEALL วนแถว table1 แล้วประเมิน table2 ต่อแถว ซึ่ง table2 อาจขึ้นกับบริบท (row context) ของ table1 GENERATEALL เหมาะกว่าเมื่อต้องการ conditional logic

ตัวอย่างจริงคำใดที่ GENERATEALL มีประโยชน์เหมาะสุด?+

ผมเจอบ่อยที่สุดคือ hierarchical expand – เช่น Region-Product matrix ต้องเห็นคู่ไหนไม่มี data ถ้าใช้ GENERATE มันตัดคู่เหล่านั้นออก แต่ GENERATEALL เก็บไว้เพื่อให้รายงาน audit ครบถ้วน

Resources & Related

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

ฟังก์ชันนี้GENERATEALLTable manipulation
Table manipulation (5)
ADDCOLUMNS

ADDCOLUMNS เป็นฟังก์ชัน table transformation ที่ใช้สำหรับเพิ่มคอลัมน์ใหม่ (Calculated Columns) เข้าไปในตารางที่มีอยู่เดิม โดยคำนวณค่าในแต่ละแถวผ่าน Row Context และส่งคืนตารางเดิมพร้อมคอลัมน์ใหม่ต่อท้าย

CROSSJOIN

CROSSJOIN สร้างตารางใหม่โดยการรวมแถวทั้งหมดจากตารางที่ระบุ โดยสร้างทุก Combination ที่เป็นไปได้ ผลลัพธ์คือตารางที่มีจำนวนแถวเท่ากับผลคูณของจำนวนแถวของแต่ละตาราง

GENERATE

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

GENERATESERIES

GENERATESERIES สร้างตารางคอลัมน์เดียวที่เป็นลำดับตัวเลขจาก StartValue ถึง EndValue ด้วย increment ที่กำหนดได้ เหมาะกับตารางช่วย parameter table หรือสร้างชุดตัวเลขสำหรับ what-if analysis

SUMMARIZE

SUMMARIZE สร้างตารางสรุปโดยจัดกลุ่มข้อมูลตามคอลัมน์ที่กำหนด คล้าย GROUP BY ใน SQL หรือ Pivot Table ใน Excel คืนค่าตารางที่มีหนึ่งแถวต่อหนึ่ง unique combination ของคอลัมน์ที่เลือก สามารถอ้างถึงคอลัมน์จาก related table ได้โดยตรงโดยไม่ต้องใช้ RELATED มักใช้สร้าง virtual table ใน measure เพื่อทำ intermediate calculations ก่อนใช้ iterator functions อย่าง SUMX, AVERAGEX คำนวณต่อ ⚠️ Best Practice: ใช้ ADDCOLUMNS ครอบ SUMMARIZE แทนการใส่ extension columns ตรงๆ เพื่อ performance และ filter context control ที่ดีกว่า สำหรับ calculated table แนะนำใช้ SUMMARIZECOLUMNS แทนเนื่องจากมี performance ดีกว่าอย่างมาก

Filter (1)
FILTER

FILTER ใช้กรองแถวในตารางตามเงื่อนไขที่ซับซ้อน โดยวนลูปทุกแถวและประเมินเงื่อนไข เหมาะกับการกรองด้วย Measure หรือ Expression ซึ่ง Boolean Expression ทำไม่ได้ แต่ต้องระวังเรื่อง Performance เพราะเป็น Iterator Function ที่ช้ากว่า Boolean Expression ดังนั้นควรใช้เฉพาะเมื่อจำเป็น และอย่าใช้ FILTER กับ RELATED เพื่อกรองข้ามตาราง ให้กรองที่ Dimension Table โดยตรงแทน

Comments

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