Thep Excel

Table.ExpandTableColumn – แตกข้อมูลจากคอลัมน์ตารางที่ซ้อนกัน

Table.ExpandTableColumn ใช้แตกข้อมูลจากคอลัมน์ที่เป็น nested table ออกมาเป็นคอลัมน์และแถวปกติในตารางหลัก โดยรักษาข้อมูลคอลัมน์อื่นไว้ และทำซ้ำแถวหลักสำหรับแต่ละแถวในตารางซ้อน มักใช้คู่กับ Table.NestedJoin หลัง join ตาราง หรือใช้ขยายข้อมูลจากแหล่งที่มีโครงสร้างแบบ hierarchical เช่น JSON หรือ API

=Table.ExpandTableColumn(table as table, column as text, columnNames as list, optional newColumnNames as nullable list) as table

By ThepExcel AI Agent
18 December 2025

Function Metrics


Popularity
9/10

Difficulty
4/10

Usefulness
9/10

Syntax & Arguments

=Table.ExpandTableColumn(table as table, column as text, columnNames as list, optional newColumnNames as nullable list) as table

Argument Type Required Default Description
table table Yes ตารางต้นทางที่มีคอลัมน์ซึ่งเก็บค่าเป็น table (nested table column)
column text Yes ชื่อคอลัมน์ที่ต้องการแตกข้อมูล ซึ่งคอลัมน์นี้ต้องมีค่าเป็น table
columnNames list Yes list ของชื่อคอลัมน์ในตารางซ้อนที่ต้องการดึงออกมาแสดง เช่น {“Name”, “Price”, “Quantity”}
newColumnNames nullable list Optional null list ของชื่อคอลัมน์ใหม่ที่จะใช้แทนชื่อเดิม เพื่อป้องกันปัญหาชื่อคอลัมน์ซ้ำกับตารางหลัก แนะนำให้ระบุเสมอเมื่อมีโอกาสชื่อซ้ำ

How it works

ขยายผลลัพธ์จาก Table.NestedJoin

หลังจากใช้ Table.NestedJoin เพื่อ join ตารางสองตารางเข้าด้วยกัน ผลลัพธ์จะมีคอลัมน์ที่เก็บตารางที่ join มา จำเป็นต้องใช้ Table.ExpandTableColumn เพื่อดึงคอลัมน์จากตารางที่ join มาแสดงในตารางหลัก

แตกข้อมูลหลังการจัดกลุ่ม (Table.Group)

เมื่อใช้ Table.Group เพื่อจัดกลุ่มข้อมูลโดยไม่ใช้ aggregation function ผลลัพธ์จะได้ตารางซ้อนที่เก็บแถวทั้งหมดในแต่ละกลุ่ม ต้องใช้ Table.ExpandTableColumn เพื่อแตกกลับมาเป็นแถวปกติ

ประมวลผลข้อมูล hierarchical จาก API หรือ JSON

ข้อมูลจาก Web API หรือไฟล์ JSON มักมีโครงสร้างแบบ nested tables (เช่น orders ที่มี order_items ซ้อนอยู่) ต้องใช้ Table.ExpandTableColumn เพื่อ flatten ข้อมูลให้อยู่ในรูป relational table

แตกข้อมูลจากฐานข้อมูลที่มีความสัมพันธ์

บาง database connector คืนผลลัพธ์แบบ nested structure เช่น query ที่มี subquery หรือข้อมูลจากหลาย table ต้องใช้ Table.ExpandTableColumn เพื่อแปลงเป็น flat table

Examples

ตัวอย่างที่ 1: การแตกคอลัมน์ตารางพื้นฐาน
let // สร้างตารางต้นทางที่มีคอลัมน์ ProductID และคอลัมน์ Details ที่เป็น table Source = Table.FromRecords({ [ ProductID = 1, Details = Table.FromRecords({ [Colo…
นี่คือตัวอย่างพื้นฐานของการแตก nested table ครับ
.
สังเกตว่า ProductID=1 มี Details 2 แถว จึงกลายเป็น 2 แถวในผลลัพธ์ ส่วน ProductID=2 มี Details 1 แถว จึงได้ 1 แถว
.
คอลัมน์ ProductID ถูก "ทำซ้ำ" ให้ตรงกับจำนวนแถวใน nested table แต่ละแถว นี่คือ concept สำคัญของ ExpandTableColumn เลยครับ 💡
Power Query Formula:

let
    // สร้างตารางต้นทางที่มีคอลัมน์ ProductID และคอลัมน์ Details ที่เป็น table
    Source = Table.FromRecords({
        [
            ProductID = 1,
            Details = Table.FromRecords({
                [Color = "Red", Size = "M"],
                [Color = "Blue", Size = "L"]
            })
        ],
        [
            ProductID = 2,
            Details = Table.FromRecords({
                [Color = "Green", Size = "S"]
            })
        ]
    }),
    
    // แตกคอลัมน์ Details ออกมาเป็นคอลัมน์ Color และ Size
    Expanded = Table.ExpandTableColumn(
        Source,
        "Details",
        {"Color", "Size"}
    )
in
    Expanded

Result:

Table ที่มี 3 แถว:
• ProductID=1, Color="Red", Size="M"
• ProductID=1, Color="Blue", Size="L"
• ProductID=2, Color="Green", Size="S"

คอลัมน์ Details ถูกแทนที่ด้วย Color และ Size

ตัวอย่างที่ 2: ใช้ newColumnNames เพื่อหลีกเลี่ยงชื่อซ้ำ
let // สร้างตารางที่มีคอลัมน์ OrderID, Amount และ Items (table) ที่มีคอลัมน์ Amount ซ้ำชื่อ Source = Table.FromRecords({ [ OrderID = 100, Amount = 5000, Items =…
ตัวอย่างนี้แสดงการใช้ argument ที่ 4 (newColumnNames) ซึ่งสำคัญมากครับ 💡
.
สังเกตว่าตารางหลักมีคอลัมน์ Amount (ยอดรวมของ order) และตารางซ้อนก็มี Amount (ราคาสินค้าแต่ละชิ้น) ถ้าไม่เปลี่ยนชื่อจะเกิด error ชื่อซ้ำทันที 😅
.
เลยต้องระบุ newColumnNames เพื่อเปลี่ยนชื่อให้ชัดเจน เช่น Amount → ItemAmount และ Product → ProductName
.
ส่วนตัวผมแนะนำให้ระบุ newColumnNames เสมอ แม้ชื่อจะไม่ซ้ำก็ตาม เพราะทำให้โค้ดอ่านง่ายและป้องกันปัญหาในอนาคต
Power Query Formula:

=let
    // สร้างตารางที่มีคอลัมน์ OrderID, Amount และ Items (table) ที่มีคอลัมน์ Amount ซ้ำชื่อ
    Source = Table.FromRecords({
        [
            OrderID = 100,
            Amount = 5000,
            Items = Table.FromRecords({
                [Product = "Laptop", Amount = 2000, Qty = 2],
                [Product = "Mouse", Amount = 500, Qty = 2]
            })
        ],
        [
            OrderID = 101,
            Amount = 1500,
            Items = Table.FromRecords({
                [Product = "Keyboard", Amount = 1500, Qty = 1]
            })
        ]
    }),
    
    // แตกคอลัมน์ Items และเปลี่ยนชื่อ Amount เป็น ItemAmount เพื่อป้องกันชื่อซ้ำ
    Expanded = Table.ExpandTableColumn(
        Source,
        "Items",
        {"Product", "Amount", "Qty"},
        {"ProductName", "ItemAmount", "Quantity"}
    )
in
    Expanded

Result:

Table ที่มี 3 แถว:
• OrderID=100, Amount=5000, ProductName="Laptop", ItemAmount=2000, Quantity=2
• OrderID=100, Amount=5000, ProductName="Mouse", ItemAmount=500, Quantity=2
• OrderID=101, Amount=1500, ProductName="Keyboard", ItemAmount=1500, Quantity=1

ไม่มีปัญหาชื่อคอลัมน์ซ้ำระหว่าง Amount (order) และ ItemAmount (item)

ตัวอย่างที่ 3: ใช้ร่วมกับ Table.NestedJoin (ขยายข้อมูลจาก join)
let // ตารางลูกค้า Customers = Table.FromRecords({ [CustomerID = 1, CustomerName = "Alice"], [CustomerID = 2, CustomerName = "Bob"] }), // ตารางคำสั่งซื้อ Order…
นี่คือ use case ที่เจอบ่อยที่สุดเลยครับ 😎
.
เราใช้ Table.NestedJoin เพื่อ join ตารางแบบ one-to-many (1 ลูกค้ามีหลาย orders) โดยเก็บตารางย่อยไว้ในคอลัมน์ CustomerOrders ก่อน
.
จากนั้นใช้ Table.ExpandTableColumn เพื่อแตกคอลัมน์ CustomerOrders ออกมา ผลลัพธ์คือแต่ละแถวของลูกค้าจะถูก "ทำซ้ำ" ตามจำนวน orders ที่มี
.
ส่วนตัวผมชอบ pattern นี้มากกว่า Table.Join ตรงๆ เพราะควบคุม join behavior ได้ละเอียดกว่า และเห็นภาพข้อมูลชัดเจนกว่า
Power Query Formula:

let
    // ตารางลูกค้า
    Customers = Table.FromRecords({
        [CustomerID = 1, CustomerName = "Alice"],
        [CustomerID = 2, CustomerName = "Bob"]
    }),
    
    // ตารางคำสั่งซื้อ
    Orders = Table.FromRecords({
        [OrderID = 101, CustomerID = 1, OrderDate = #date(2024, 1, 15), Total = 2500],
        [OrderID = 102, CustomerID = 1, OrderDate = #date(2024, 2, 10), Total = 1200],
        [OrderID = 103, CustomerID = 2, OrderDate = #date(2024, 1, 20), Total = 3000]
    }),
    
    // Join ตารางโดยเก็บผลลัพธ์ไว้ใน nested table
    Joined = Table.NestedJoin(
        Customers,
        {"CustomerID"},
        Orders,
        {"CustomerID"},
        "CustomerOrders",
        JoinKind.LeftOuter
    ),
    
    // แตกคอลัมน์ CustomerOrders เพื่อดึงข้อมูล OrderDate และ Total
    Expanded = Table.ExpandTableColumn(
        Joined,
        "CustomerOrders",
        {"OrderID", "OrderDate", "Total"},
        {"OrderID", "OrderDate", "OrderTotal"}
    )
in
    Expanded

Result:

Table ที่มี 3 แถว:
• CustomerID=1, CustomerName="Alice", OrderID=101, OrderDate=2024-01-15, OrderTotal=2500
• CustomerID=1, CustomerName="Alice", OrderID=102, OrderDate=2024-02-10, OrderTotal=1200
• CustomerID=2, CustomerName="Bob", OrderID=103, OrderDate=2024-01-20, OrderTotal=3000

ข้อมูลลูกค้าถูกทำซ้ำสำหรับแต่ละ order

ตัวอย่างที่ 4: เลือกแตกเฉพาะบางคอลัมน์จากตารางซ้อน
let // สร้างตารางที่มีข้อมูลพนักงานและประวัติการทำงาน Source = Table.FromRecords({ [ EmployeeID = "E001", EmployeeName = "John Doe", Department = "Sales", WorkH…
ตัวอย่างนี้แสดงเทคนิคที่สำคัญมากครับ ไม่จำเป็นต้องแตกทุกคอลัมน์จากตารางซ้อน 💡
.
สังเกตว่าตาราง WorkHistory มี 5 คอลัมน์ แต่เราเลือกแตกแค่ 3 คอลัมน์ที่สนใจ (Company, Position, Years) ไม่เอา Salary และ StartDate
.
วิธีนี้ช่วยลดขนาดข้อมูล ทำให้ query เร็วขึ้น และตารางอ่านง่ายขึ้นด้วย
.
ส่วนตัวผมมักใช้เทคนิคนี้เพื่อเลือกเฉพาะข้อมูลที่จำเป็นจริงๆ และเปลี่ยนชื่อให้มีความหมายชัดเจน เช่น Company → PreviousCompany เพื่อให้รู้ว่านี่คือข้อมูลในอดีต
Power Query Formula:

let
    // สร้างตารางที่มีข้อมูลพนักงานและประวัติการทำงาน
    Source = Table.FromRecords({
        [
            EmployeeID = "E001",
            EmployeeName = "John Doe",
            Department = "Sales",
            WorkHistory = Table.FromRecords({
                [Company = "ABC Corp", Position = "Sales Rep", Years = 3, Salary = 50000, StartDate = #date(2019, 1, 1)],
                [Company = "XYZ Ltd", Position = "Sales Manager", Years = 2, Salary = 70000, StartDate = #date(2022, 6, 1)]
            })
        ],
        [
            EmployeeID = "E002",
            EmployeeName = "Jane Smith",
            Department = "IT",
            WorkHistory = Table.FromRecords({
                [Company = "Tech Inc", Position = "Developer", Years = 5, Salary = 80000, StartDate = #date(2018, 3, 15)]
            })
        ]
    }),
    
    // แตกเฉพาะคอลัมน์ Company, Position และ Years จาก WorkHistory (ไม่เอา Salary และ StartDate)
    Expanded = Table.ExpandTableColumn(
        Source,
        "WorkHistory",
        {"Company", "Position", "Years"},
        {"PreviousCompany", "PreviousPosition", "YearsWorked"}
    )
in
    Expanded

Result:

Table ที่มี 3 แถว:
• EmployeeID="E001", EmployeeName="John Doe", Department="Sales", PreviousCompany="ABC Corp", PreviousPosition="Sales Rep", YearsWorked=3
• EmployeeID="E001", EmployeeName="John Doe", Department="Sales", PreviousCompany="XYZ Ltd", PreviousPosition="Sales Manager", YearsWorked=2
• EmployeeID="E002", EmployeeName="Jane Smith", Department="IT", PreviousCompany="Tech Inc", PreviousPosition="Developer", YearsWorked=5

คอลัมน์ Salary และ StartDate ไม่ถูกดึงออกมา

FAQs

ถ้าไม่ระบุ newColumnNames จะเกิดอะไรขึ้น?

ถ้าไม่ระบุ newColumnNames ฟังก์ชันจะใช้ชื่อเดิมจากคอลัมน์ในตารางซ้อน ซึ่งอาจทำให้เกิดปัญหาชื่อคอลัมน์ซ้ำกับตารางหลักและเกิด error ได้
.
ยกตัวอย่างเช่น ถ้าตารางหลักมีคอลัมน์ “Amount” และตารางซ้อนก็มี “Amount” พอแตกออกมาจะมีชื่อซ้ำกัน Power Query จะ error ทันที 😭
.
ส่วนตัวผมแนะนำให้ระบุ newColumnNames เสมอครับ แม้ว่าชื่อจะไม่ซ้ำก็ตาม เพราะทำให้โค้ดอ่านง่ายและป้องกันปัญหาในอนาคต

ถ้าตารางซ้อนเป็น empty table (ไม่มีแถว) จะเกิดอะไรขึ้น?

ถ้าตารางซ้อนไม่มีแถว (empty table) แถวนั้นจะหายไปจากผลลัพธ์เลยครับ 😭
.
ทำงานเหมือน Inner Join นั่นเอง ยกตัวอย่าง ถ้าใช้ Table.NestedJoin แบบ LeftOuter แล้วบางแถวไม่มีข้อมูล join ได้ (nested table ว่างเปล่า) พอเรา expand ออกมา… แถวนั้นจะหายไป
.
นี่เป็นพฤติกรรมที่ต้องระวังมากครับ ถ้าต้องการรักษาแถวเอาไว้ ต้องตรวจสอบก่อน expand ด้วย Table.RowCount หรือใช้ conditional logic เพื่อจัดการ case นี้

ต่างจาก Table.ExpandRecordColumn อย่างไร?

คำถามนี้เจอบ่อยมากครับ เพราะชื่อคล้ายกันมาก 😅
.
**Table.ExpandTableColumn** → แตก nested **table** ซึ่ง 1 แถวอาจกลายเป็นหลายแถว (one-to-many)
.
**Table.ExpandRecordColumn** → แตก **record** ซึ่ง 1 แถวยังคงเป็น 1 แถว (one-to-one) แค่เพิ่มคอลัมน์เข้ามา
.
ใช้ **ExpandTableColumn** เมื่อ: คอลัมน์เป็น table และต้องการ flatten ทุกแถว (เช่น 1 order มีหลาย items)
.
ใช้ **ExpandRecordColumn** เมื่อ: คอลัมน์เป็น record และต้องการดึง field ออกมา (เช่น address record ที่มี street, city, zip)

สามารถแตกหลายคอลัมน์ตารางพร้อมกันได้หรือไม่?

ไม่ได้โดยตรงครับ Table.ExpandTableColumn แตกได้ทีละ 1 คอลัมน์เท่านั้น
.
ถ้ามีหลายคอลัมน์ที่เป็น table ต้องเรียกฟังก์ชันนี้หลายครั้งต่อเนื่องกัน แบบนี้:
.
“`
ExpandTableColumn(
ExpandTableColumn(Source, “Col1”, …),
“Col2”,

)
“`
.
หรือใช้ step แยกกันใน Power Query Editor ซึ่งอ่านง่ายกว่า ส่วนตัวผมชอบแยก step เพราะ debug ง่ายกว่าครับ 😎

จะป้องกันตารางขยายใหญ่เกินไป (data explosion) ได้อย่างไร?

นี่เป็นปัญหาใหญ่ที่เจอบ่อยมากครับ 😭 ตารางที่มี 100 แถว ถ้าแต่ละแถวมี nested table 1,000 แถว พอ expand ได้ 100,000 แถวเลย!
.
**วิธีป้องกัน:**
.
1. **ตรวจสอบก่อน expand** ด้วย Table.AddColumn:
“`
Table.AddColumn(Source, “RowCount”, each Table.RowCount([Details]))
“`
.
2. **จำกัดจำนวนแถว** ก่อน expand:
“`
Table.TransformColumns(Source, {{“Details”, each Table.FirstN(_, 10)}})
“`
.
3. **กรองข้อมูล** ที่ไม่จำเป็นออกก่อน:
“`
Table.SelectRows(Source, each Table.RowCount([Details]) <= 100)
“`
.
ส่วนตัวผมแนะนำให้ตรวจสอบก่อนเสมอครับ เพื่อป้องกัน performance issue และ memory overflow

Resources & Related

Additional Notes

Table.ExpandTableColumn เป็นฟังก์ชันสำคัญใน Power Query ที่ใช้แตกข้อมูลจากคอลัมน์ที่มีค่าเป็น Table (Nested Table หรือตารางซ้อน) ให้กลายเป็นคอลัมน์ปกติในตารางหลัก ซึ่งแต่ละแถวในตารางย่อยจะกลายเป็นแถวใหม่ในตารางผลลัพธ์ครับ

.

ฟังก์ชันนี้มักใช้คู่กับ Table.NestedJoin เมื่อทำการ join ตารางแล้วต้องการดึงข้อมูลจากตารางที่ join มาแสดง หรือใช้หลังจากทำ Table.Group เพื่อแตกข้อมูลจากผลลัพธ์ที่จัดกลุ่มไว้

.

นอกจากนี้ยังใช้ขยายข้อมูลที่ได้จากแหล่งข้อมูลภายนอกเช่น Web API, ฐานข้อมูล หรือไฟล์ที่มีโครงสร้างแบบ nested structure ซึ่งเจอบ่อยมากเวลาทำงานกับ JSON หรือ API response 😎

.

การทำงานของ Table.ExpandTableColumn คือการรักษาคอลัมน์อื่นๆ ในตารางหลักไว้ แล้วดึงคอลัมน์ที่ต้องการจากตารางซ้อนมาเพิ่มเป็นคอลัมน์ใหม่

.

โดยแต่ละแถวในตารางย่อยจะถูก “ทำซ้ำ” พร้อมกับข้อมูลจากแถวหลัก ทำให้ได้โครงสร้างข้อมูลแบบ flat table ที่สามารถวิเคราะห์และใช้งานได้ง่ายครับ 💡

Leave a Reply

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