1. แนวคิดของการวิเคราะห์รวม
การดำเนินการรวมเป็นแนวคิดที่สำคัญมากในการคิวรีฐานข้อมูล ซึ่งมักนำมาใช้สำหรับการวิเคราะห์ทางสถิติ เช่น การรวมผลรวม การนับจำนวน ค่าเฉลี่ย ค่าสูงสุด และค่าต่ำสุด การดำเนินการเหล่านี้ช่วยให้ผู้ใช้สามารถสกัดข้อมูลที่มีปริมาณมากได้อย่างมีนัยสำคัญ และเป็นการสนับสนุนในการวิเคราะห์ข้อมูลและการตัดสินใจ ฟังก์ชันที่ทำงานรวมกันในฐานข้อมูลสำหรับการรวมเป็นทางศาสตร์แทนว่าฟังก์ชันรวม
2. การดำเนินการรวมพื้นฐาน
2.1 แนวคิดของฟังก์ชันรวม
ฟังก์ชันรวมเป็นฟังก์ชันที่ใช้ในภาษาคิวรีของฐานข้อมูลสำหรับดำเนินการคำนวณชุดข้อมูลและคืนค่าเดียว ใน SQL และภาษาคิวรีที่คล้ายกัน ฟังก์ชันรวมสามารถดำเนินการกับคอลัมน์ของข้อมูลและคืนค่าเดียว เช่น ผลรวม (SUM), ค่าเฉลี่ย (AVG), จำนวน (COUNT), ค่าสูงสุด (MAX), และค่าต่ำสุด (MIN) เมื่อเราต้องการดำเนินการวิเคราะห์ทางสถิติของข้อมูล ฟังก์ชันรวมเป็นเครื่องมือที่สำคัญสำหรับการประมวลผลชุดข้อมูลและสกัดข้อมูลทางสถิติ
2.2 การรวมด้วยฟิลด์เดี่ยว
ในการประยุกต์ใช้ การวิเคราะห์ข้อมูลทางรวมด้วยฟิลด์เดี่ยวเป็นความต้องการที่พบบ่อย โดยมักใช้สำหรับการได้ผลข้อมูลทางสถิติ เช่น ผลรวม ค่าเฉลี่ย ค่าสูงสุด และค่าต่ำสุด ของคอลัมน์ที่เจาะจง สมมุติว่าเรามีตารางข้อมูลเกี่ยวกับข้อมูลการชำระเงิน และต้องการคำนวณยอดรวมของเงินที่ผู้ใช้ชำระ โดยใช้เฟรมเวิร์ก ent
เราสามารถสร้างคิวรีจากเอนทิตีและประยุกต์ใช้ฟังก์ชันรวมตามนี้:
func Do(ctx context.Context, client *ent.Client) {
// คำนวณผลรวมของฟิลด์ Amount สำหรับเอนทิตีการชำระเงิน
sum, err := client.Payment.Query().
Aggregate(
ent.Sum(payment.Amount),
).
Int(ctx)
if err != nil {
log.Fatalf("การรับค่าผลรวมล้มเหลว: %v", err)
}
log.Printf("ยอดเงินทั้งหมดของการชำระเงิน: %d", sum)
}
ในโค้ดตัวอย่างข้างต้น เราเริ่มคิวรีสำหรับเอนทิตีการชำระเงินโดยใช้ client.Payment.Query()
จากนั้นใช้วิธี Aggregate()
เพื่อเรียกใช้ฟังก์ชัน ent.Sum
ด้วยพารามิเตอร์เป็น payment.Amount
เพื่อคำนวณยอดเงินรวม เราใช้ .Int(ctx)
เพื่อแปลงผลรวมรวมเป็นจำนวนเต็ม และบันทึกไว้
2.3 การรวมด้วยฟิลด์มากกว่าหนึ่ง
ในกรณีมากมาย เราต้องการดำเนินการรวมบนฟิลด์มากกว่าหนึ่ง ไม่ใช่แค่หนึ่งเท่านั้น ในส่วนนี้ เราจะสาธิตวิธีในการทำค่ารวมของฟิลด์มากกว่าหนึ่งผ่านตัวอย่าง
ในตัวอย่างนี้ เราจะทำการรวมผลรวม หาค่าต่ำสุด หาค่าสูงสุด และนับฟิลด์ Age
ในตารางสัตว์เลี้ยง
func Do(ctx context.Context, client *ent.Client) {
var v []struct {
Sum, Min, Max, Count int
}
err := client.Pet.Query().
Aggregate(
ent.Sum(pet.FieldAge), // ผลรวมของอายุ
ent.Min(pet.FieldAge), // อายุขั้นต่ำ
ent.Max(pet.FieldAge), // อายุสูงสุด
ent.Count(), // นับ
).
Scan(ctx, &v)
if err != nil {
log.Fatalf("คิวรีล้มเหลว: %v", err)
}
// แสดงผลลัพธ์รวมทั้งหมด
for _, agg := range v {
fmt.Printf("ผลรวม: %d ต่ำสุด: %d สูงสุด: %d นับ: %d\n", agg.Sum, agg.Min, agg.Max, agg.Count)
}
}
ในโค้ดข้างต้น เราใช้ฟังก์ชัน Aggregate
เพื่อดำเนินการรวมหลายฟิลด์ และใช้ฟังก์ชัน Scan
เพื่อเก็บผลการรวมในสไลซ์ v
จากนั้น เราวนลูปที่ v
เพื่อแสดงผลลัพธ์การรวมทั้งหมด
3. การประยุกต์ใช้การรวมแบบ Group By
3.1 การใช้ Group By เพื่อจัดกลุ่มฟิลด์
ในการดำเนินการของฐานข้อมูล คำสั่ง Group By
เป็นวิธีที่สามารถใช้ในการจัดกลุ่มข้อมูล ในส่วนนี้ เราจะเรียนรู้วิธีในการใช้ Group By
เพื่อจัดกลุ่มข้อมูลในฐานข้อมูล
ตัวอย่างการจัดกลุ่มฟิลด์หนึ่งหรือมากกว่าในการใช้ Group By
สมมติว่าเรามีตารางข้อมูลของผู้ใช้และต้องการจัดกลุ่มฟิลด์ name
ของผู้ใช้และคำนวณจำนวนของผู้ใช้ในแต่ละกลุ่ม ด้านล่างนี้คือตัวอย่างโค้ดเรื่องการวิธีแสดงผลการทำงาน:
func Do(ctx context.Context, client *ent.Client) {
names, err := client.User.
Query().
GroupBy(user.FieldName).
Strings(ctx)
if err != nil {
log.Fatalf("การดำเนินการคิวรีแบบกลุ่มล้มเหลว: %v", err)
}
// แสดงชื่อของแต่ละกลุ่ม
for _, name := range names {
fmt.Println("ชื่อกลุ่ม:", name)
}
}
ในโค้ดข้างต้น เราใช้วิธี GroupBy
ของตัวสร้างคิวรีเพื่อระบุฟิลด์ที่เราต้องการจัดกลุ่มโดย
3.2. การจัดกลุ่มและการรวมข้อมูลจากหลายฟิลด์
บางครั้งเราต้องการจัดกลุ่มข้อมูลโดยใช้หลายฟิลด์และดำเนินการฟังก์ชันการรวมข้อมูลในแต่ละกลุ่ม ด้านล่างนี้เป็นตัวอย่างของวิธีการที่จะบรรลุความต้องการนี้:
โค้ดต่อไปนี้โดยที่แสดงให้เห็นว่าจะทำการจัดกลุ่มข้อมูลในตารางผู้ใช้ตามฟิลด์ name
และ age
และคำนวณอายุรวมและจำนวนผู้ใช้ในแต่ละกลุ่ม
func Do(ctx context.Context, client *ent.Client) {
var v []struct {
Name string `json:"name"`
Age int `json:"age"`
Sum int `json:"sum"`
Count int `json:"count"`
}
err := client.User.Query().
GroupBy(user.FieldName, user.FieldAge).
Aggregate(ent.Count(), ent.Sum(user.FieldAge)).
Scan(ctx, &v)
if err != nil {
log.Fatalf("Failed to execute multiple fields grouping and aggregation query: %v", err)
}
// แสดงข้อมูลโดยละเอียดสำหรับแต่ละกลุ่ม
for _, group := range v {
fmt.Printf("Name: %s Age: %d Sum: %d Count: %d\n", group.Name, group.Age, group.Sum, group.Count)
}
}
ในตัวอย่างนี้ เราไม่เพียงแค่จัดกลุ่มข้อมูลตามฟิลด์ name
และ age
ในตารางผู้ใช้ แต่ยังใช้ฟังก์ชันการรวม Count
และ Sum
เพื่อคำนวณจำนวนรวมและอายุรวมในแต่ละกลุ่ม
4. การใช้ Having ร่วมกับ Group By
คลอส Having
จะกรองผลลัพธ์ที่ได้จากการรวมหลังจากการดำเนินการ Group By
ตัวอย่างต่อไปนี้แสดงวิธีเลือกเฉพาะผู้ใช้ที่มีอายุสูงสุดในแต่ละบทบาท:
func Do(ctx context.Context, client *ent.Client) {
var users []struct {
Id Int
Age Int
Role string
}
err := client.User.Query().
Modify(func(s *sql.Selector) {
s.GroupBy(user.FieldRole)
s.Having(
sql.EQ(
user.FieldAge,
sql.Raw(sql.Max(user.FieldAge)),
),
)
}).
ScanX(ctx, &users)
if err != nil {
log.Fatalf("Failed to execute Having combined with Group By query: %v", err)
}
// แสดงข้อมูลผู้ใช้ที่ทำให้เงื่อนไข Having เป็นจริง
for _, user := range users {
fmt.Printf("ID: %d Age: %d Role: %s\n", user.Id, user.Age, user.Role)
}
}
โค้ดข้างต้นจะสร้างคิวรี่ SQL เทียบเท่าเพื่อเลือกผู้ใช้ที่มีอายุสูงสุดในแต่ละบทบาท