GENERATEALL วนแถวของตาราง 1 แล้วสร้าง Cartesian product กับผลลัพธ์ของตาราง 2 โดยคงแถวที่ไม่มีข้อมูลย่อย ต่างจาก GENERATE ตรงที่ไม่ตัดแถวหลักออก
=GENERATEALL(<table1>, <table2>)
=GENERATEALL(<table1>, <table2>)
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| table1 | table | Yes | ตารางหลักที่จะวนแถวทีละแถว ต้องเป็นนิพจน์ DAX ที่คืนตาราง | |
| table2 | table | Yes | นิพจน์ตารางที่ประเมินแยกต่อแถวของ table1 ใน row context ของแถวปัจจุบัน อาจคืนผลว่าง (ไม่มีแถว) แต่จะถูกเก็บไว้ในผลลัพธ์ final |
เหมาะกับงานตรวจสอบ/การวิเคราะห์ที่ไม่อยากให้แถวหายไปเมื่อไม่มีข้อมูลย่อย
เช่น ตรวจว่ารายการไหนไม่มีข้อมูลย่อย
Product Sales Coverage = GENERATEALL( Products, FILTER(Sales, Sales[ProductID] = Products[ProductID]) )Product Sales Coverage =
GENERATEALL(
Products,
FILTER(Sales, Sales[ProductID] = Products[ProductID])
)
ตารางที่มีสินค้าทั้งหมด รวมสินค้าที่ไม่มี Sales record
GENERATE Example = GENERATE( Products, FILTER(Sales, Sales[ProductID] = Products[ProductID]) )GENERATE Example =
GENERATE(
Products,
FILTER(Sales, Sales[ProductID] = Products[ProductID])
)
ตารางเฉพาะสินค้าที่มี Sales record (ตัดสินค้าที่ไม่มีขายออก)
Date Range Expansion = GENERATEALL( DISTINCT(Orders[OrderDate]), FILTER( CALENDAR([OrderDate], DATE(2025, 12, 31)), [Date] >= Orders[OrderDate] ) )Date Range Expansion =
GENERATEALL(
DISTINCT(Orders[OrderDate]),
FILTER(
CALENDAR([OrderDate], DATE(2025, 12, 31)),
[Date] >= Orders[OrderDate]
)
)
ตารางขยายที่มีทุกวันตั้งแต่ Order Date ไป ปลายปี แม้ไม่มีรายการ
Product Analysis = VAR ProductsSummary = ADDCOLUMNS( Products, "Sales Count", COUNTROWS(FILTER(Sales, Sales[ProductID] = Products[ProductID])) ) RETURN GENERATE…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()
)
)
ตารางขยายที่มีผลลัพธ์เฉพาะสินค้าที่มีขาย แต่คงโครงสร้างเดียว
เวลา table2 ให้ผลว่าง (ไม่มีแถว) สำหรับบางแถวของ table1 GENERATE ตัดแถวเหล่านั้นออก แต่ GENERATEALL เก็บไว้พร้อม null values ที่เหมาะสำหรับการตรวจสอบครบถ้วน
ได้ ผม มักใช้ GENERATEALL รวมกับ COUNTROWS หรือ COALESCE เพื่อตรวจว่าแถวไหนไม่มีข้อมูลจาก table2 ลองแล้วจะเห็นความ valuable ในการ audit
CROSSJOIN สร้าง Cartesian product ธรรมชาติ (ทุกคู่) GENERATEALL วนแถว table1 แล้วประเมิน table2 ต่อแถว ซึ่ง table2 อาจขึ้นกับบริบท (row context) ของ table1 GENERATEALL เหมาะกว่าเมื่อต้องการ conditional logic
ผมเจอบ่อยที่สุดคือ hierarchical expand – เช่น Region-Product matrix ต้องเห็นคู่ไหนไม่มี data ถ้าใช้ GENERATE มันตัดคู่เหล่านั้นออก แต่ GENERATEALL เก็บไว้เพื่อให้รายงาน audit ครบถ้วน
GENERATEALL คือฟังก์ชันสำคัญในเมื่อต้องการรวมตารางสองตารางแบบ outer apply ทำงานโดยวนแถวของ Table1 ทีละแถว แล้วประเมิน Table2 ในบริบทของแถวนั้น สร้าง Cartesian product จากผลลัพธ์ และสำคัญตรงนี้ – ถ้า Table2 ให้ผลว่างสำหรับแถวใดแถวหนึ่ง แถวนั้นจะถูกเก็บไว้ในผลลัพธ์พร้อม null values สำหรับคอลัมน์ของ Table2
ที่เจ๋งคือการทำงานแบบ outer apply นี้มีประโยชน์มากสำหรับการหา records ที่ไม่มี match ในตารางที่สอง เช่น สินค้าที่ไม่มีรายการขาย หรือลูกค้าที่ไม่มีธุรกรรม ถ้าใช้ GENERATE ธรรมดา มันจะตัดแถวเหล่านั้นออกไป แต่ GENERATEALL เก็บไว้เพื่อให้คุณเห็นความครอบคลุมที่แท้จริง
ส่วนตัวผมใช้ GENERATEALL เวลาต้องการ audit หรือ gap analysis – หาว่าสินค้าไหนขายไม่ออก ลูกค้าไหนไม่ซื้อ หรือคู่ region-product ไหนไม่มีข้อมูล ทำให้รายงานครบถ้วนและเห็นจุดที่ควรปรับปรุง