DJANGO
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.

Sử dụng Group By trong Django ORM với Python

Trong bài viết này, bạn sẽ học cách sử dụng Django Group By kết hợp với các hàm tổng hợp để tính toán các giá trị tổng hợp cho từng nhóm. Các hàm tổng hợp như count, min, max, avg, và sum thường được sử dụng cùng với mệnh đề GROUP BY trong SQL để trả về các giá trị tổng hợp cho mỗi nhóm dữ liệu. Django cung cấp các phương thức mạnh mẽ như annotate()values() giúp bạn dễ dàng thực hiện các thao tác này trực tiếp trên các QuerySet. Bài viết này sẽ giúp bạn nắm vững cách sử dụng các phương thức này qua các ví dụ thực tế, từ đó tối ưu hóa các truy vấn cơ sở dữ liệu trong dự án Django của bạn.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Giới thiệu về Django Group By trong Python

Câu lệnh SQL GROUP BY nhóm các hàng được trả về bởi một truy vấn thành các nhóm. Thông thường, bạn sử dụng các hàm tổng hợp như count, min, max, avg, và sum với mệnh đề GROUP BY để trả về một giá trị tổng hợp cho mỗi nhóm.

Dưới đây là cách sử dụng cơ bản của mệnh đề GROUP BY trong một câu lệnh SELECT:

SELECT column_1, AGGREGATE(column_2)
FROM table_name
#Bài viết này được đăng tại freetuts.net
GROUP BY column1;

Trong Django, bạn có thể sử dụng phương thức annotate() kết hợp với values() để áp dụng tổng hợp trên các nhóm như sau:

Bài viết này được đăng tại [free tuts .net]

(Entity.objects
    .values('column_2')
    .annotate(value=AGGREGATE('column_1'))
)

Trong cú pháp này:

  • values('column_2') – truyền cột mà bạn muốn nhóm vào phương thức values().
  • annotate(value=AGGREGATE('column_1')) – chỉ định tổng hợp nào sẽ được áp dụng trong phương thức annotate().

Lưu ý rằng thứ tự gọi values()annotate() rất quan trọng. Nếu bạn không gọi phương thức values() trước và annotate() sau, biểu thức sẽ không tạo ra kết quả tổng hợp.

Ví dụ về Django Group By trong Python

Mình sẽ sử dụng các mô hình Employee và Department từ ứng dụng HR để minh họa. Các mô hình Employee và Department được ánh xạ tới các bảng hr_employee và hr_department trong cơ sở dữ liệu:

django orm employee department png

Django Group By với Count

Ví dụ sau sử dụng các phương thức values()annotate() để lấy số lượng nhân viên theo từng phòng ban:

>>> (Employee.objects
...     .values('department')
...     .annotate(head_count=Count('department'))
...     .order_by('department')
...  )
#Bài viết này được đăng tại freetuts.net
SELECT "hr_employee"."department_id",
       COUNT("hr_employee"."department_id") AS "head_count"
  FROM "hr_employee"
 GROUP BY "hr_employee"."department_id"
 ORDER BY "hr_employee"."department_id" ASC
 LIMIT 21
Execution time: 0.001492s [Database: default]
<QuerySet [{'department': 1, 'head_count': 30}, {'department': 2, 'head_count': 40}, {'department': 3, 'head_count': 28}, {'department': 4, 'head_count': 29}, {'department': 5, 'head_count': 29}, {'department': 6, 'head_count': 30}, {'department': 7, 'head_count': 34}]>

Cách hoạt động:

Đầu tiên, nhóm các nhân viên theo phòng ban bằng phương thức values():

values('department')

Thứ hai, áp dụng Count() cho mỗi nhóm:

annotate(head_count=Count('department'))

Thứ ba, sắp xếp các đối tượng trong QuerySet theo phòng ban:

order_by('department')

Phía sau, Django thực thi câu lệnh SELECT với mệnh đề GROUP BY:

SELECT "hr_employee"."department_id",
       COUNT("hr_employee"."department_id") AS "head_count"
  FROM "hr_employee"
#Bài viết này được đăng tại freetuts.net
 GROUP BY "hr_employee"."department_id"
 ORDER BY "hr_employee"."department_id" ASC
 LIMIT 21

Django Group By với Sum

Tương tự, bạn có thể sử dụng Sum() để tính tổng lương của nhân viên trong từng phòng ban:

>>> (Employee.objects
...     .values('department')
...     .annotate(total_salary=Sum('salary'))
...     .order_by('department')
...  )
SELECT "hr_employee"."department_id",
       SUM("hr_employee"."salary") AS "total_salary"
  FROM "hr_employee"
#Bài viết này được đăng tại freetuts.net
 GROUP BY "hr_employee"."department_id"
 ORDER BY "hr_employee"."department_id" ASC
#Bài viết này được đăng tại freetuts.net
 LIMIT 21
Execution time: 0.000927s [Database: default]
<QuerySet [{'department': 1, 'total_salary': Decimal('3615341.00')}, {'department': 2, 'total_salary': Decimal('5141611.00')}, {'department': 3, 'total_salary': Decimal('3728988.00')}, {'department': 4, 'total_salary': Decimal('3955669.00')}, {'department': 5, 'total_salary': Decimal('4385784.00')}, {'department': 6, 'total_salary': Decimal('4735927.00')}, {'department': 7, 'total_salary': Decimal('4598788.00')}]>

Django Group By với Min, Max và Avg

Ví dụ sau áp dụng nhiều hàm tổng hợp cho các nhóm để lấy lương thấp nhất, trung bình và cao nhất của nhân viên trong từng phòng ban:

>>> (Employee.objects
...     .values('department')
...     .annotate(
...         min_salary=Min('salary'),
...         max_salary=Max('salary'),
...         avg_salary=Avg('salary')
...     )
...     .order_by('department')
...  )
#Bài viết này được đăng tại freetuts.net
SELECT "hr_employee"."department_id",
       MIN("hr_employee"."salary") AS "min_salary",
       MAX("hr_employee"."salary") AS "max_salary",
       AVG("hr_employee"."salary") AS "avg_salary"
  FROM "hr_employee"
 GROUP BY "hr_employee"."department_id"
 ORDER BY "hr_employee"."department_id" ASC
 LIMIT 21
#Bài viết này được đăng tại freetuts.net
Execution time: 0.001670s [Database: default]
<QuerySet [{'department': 1, 'min_salary': Decimal('45427.00'), 'max_salary': Decimal('149830.00'), 'avg_salary': Decimal('120511.366666666667')}, {'department': 2, 'min_salary': Decimal('46637.00'), 'max_salary': Decimal('243462.00'), 'avg_salary': Decimal('128540.275000000000')}, {'department': 3, 'min_salary': Decimal('40762.00'), 'max_salary': Decimal('248265.00'), 'avg_salary': Decimal('133178.142857142857')}, {'department': 4, 'min_salary': Decimal('43000.00'), 'max_salary': Decimal('238016.00'), 'avg_salary': Decimal('136402.379310344828')}, {'department': 5, 'min_salary': Decimal('42080.00'), 'max_salary': Decimal('246403.00'), 'avg_salary': Decimal('151233.931034482759')}, {'department': 6, 'min_salary': Decimal('58356.00'), 'max_salary': Decimal('248312.00'), 'avg_salary': Decimal('157864.233333333333')}, {'department': 7, 'min_salary': Decimal('40543.00'), 'max_salary': Decimal('238892.00'), 'avg_salary': Decimal('135258.470588235294')}]>

Django Group By với Join

Ví dụ sau sử dụng các phương thức values()annotate() để lấy số lượng nhân viên trong mỗi phòng ban:

>>> (Department.objects
...     .values('name')
...     .annotate(
...         head_count=Count('employee')
...     )
...  )
#Bài viết này được đăng tại freetuts.net
SELECT "hr_department"."name",
       COUNT("hr_employee"."id") AS "head_count"
  FROM "hr_department"
  LEFT OUTER JOIN "hr_employee"
    ON ("hr_department"."id" = "hr_employee"."department_id")
 GROUP BY "hr_department"."name"
 LIMIT 21
Execution time: 0.001953s [Database: default]
<QuerySet [{'name': 'Marketing', 'head_count': 28}, {'name': 'Finance', 'head_count': 29}, {'name': 'SCM', 'head_count': 29}, {'name': 'GA', 'head_count': 30}, {'name': 'Sales', 'head_count': 40}, {'name': 'IT', 'head_count': 30}, {'name': 'HR', 'head_count': 34}]>

Cách hoạt động:

  • values('name') – nhóm các phòng ban theo tên.
  • annotate(headcount=Count('employee')) – đếm số lượng nhân viên trong mỗi phòng ban.

Phía sau, Django sử dụng LEFT JOIN để kết nối bảng hr_department với bảng hr_employee và áp dụng hàm COUNT() cho mỗi nhóm.

Django Group By với Having trong Python

Để áp dụng điều kiện cho các nhóm, bạn sử dụng phương thức filter(). Ví dụ, đoạn mã sau sử dụng phương thức filter() để lấy các phòng ban có số lượng nhân viên lớn hơn 30:

>>> (Department.objects
...     .values('name')
...     .annotate(
...         head_count=Count('employee')
...     )
...     .filter(head_count__gt=30)
...  )
#Bài viết này được đăng tại freetuts.net
SELECT "hr_department"."name",
       COUNT("hr_employee"."id") AS "head_count"
  FROM "hr_department"
  LEFT OUTER JOIN "hr_employee"
    ON ("hr_department"."id" = "hr_employee"."department_id")
 GROUP BY "hr_department"."name"
HAVING COUNT("hr_employee"."id") > 30
#Bài viết này được đăng tại freetuts.net
 LIMIT 21
Execution time: 0.002893s [Database: default]
<QuerySet [{'name': 'Sales', 'head_count': 40}, {'name': 'HR', 'head_count': 34}]>

Phía sau, Django sử dụng mệnh đề HAVING để lọc các nhóm dựa trên điều kiện mà mình truyền vào phương thức filter():

SELECT "hr_department"."name",
       COUNT("hr_employee"."id") AS "head_count"
  FROM "hr_department"
#Bài viết này được đăng tại freetuts.net
  LEFT OUTER JOIN "hr_employee"
    ON ("hr_department"."id" = "hr_employee"."department_id")
 GROUP BY "hr_department"."name"
HAVING COUNT("hr_employee"."id") > 30

Kết bài

Qua hướng dẫn này, bạn đã học cách sử dụng values()annotate() để nhóm các hàng thành các nhóm và tính toán các giá trị tổng hợp như count, sum, min, max, và avg. Đồng thời, bạn cũng biết cách sử dụng phương thức filter() để thêm điều kiện lọc cho các nhóm. Việc nắm vững các kỹ thuật này sẽ giúp bạn thực hiện các truy vấn phức tạp và tối ưu hóa hiệu suất truy vấn trong dự án Django của mình một cách hiệu quả. Hy vọng rằng những kiến thức này sẽ hỗ trợ bạn trong việc phát triển các ứng dụng Django mạnh mẽ và linh hoạt.

Cùng chuyên mục:

Cách thêm Progress Bar trong Python với chỉ một dòng Code

Cách thêm Progress Bar trong Python với chỉ một dòng Code

Toán tử Walrus Operator- Tính năng mới trong Python 3.8

Toán tử Walrus Operator- Tính năng mới trong Python 3.8

Cách nạp dữ liệu Machine Learning từ File trong Python

Cách nạp dữ liệu Machine Learning từ File trong Python

Hướng dẫn sử dụng Google Sheets API với Python

Hướng dẫn sử dụng Google Sheets API với Python

Xây dựng  web Python tự động hóa Twitter | Flask, Heroku, Twitter API & Google Sheets API

Xây dựng web Python tự động hóa Twitter | Flask, Heroku, Twitter API & Google Sheets API

Xây dựng Web Machine Learning đẹp mắt với Streamlit và Scikit-learn trong Python

Xây dựng Web Machine Learning đẹp mắt với Streamlit và Scikit-learn trong Python

Hướng dẫn tạo Chatbot đơn giản bằng PyTorch

Hướng dẫn tạo Chatbot đơn giản bằng PyTorch

11 mẹo và thủ thuật để viết Code Python hiệu quả hơn

11 mẹo và thủ thuật để viết Code Python hiệu quả hơn

Hướng dẫn làm ứng dụng TODO với Flask dành cho người mới bắt đầu trong Python

Hướng dẫn làm ứng dụng TODO với Flask dành cho người mới bắt đầu trong Python

Hướng dẫn viết Snake Game bằng Python

Hướng dẫn viết Snake Game bằng Python

Cách sử dụng chế độ interactive trong Python

Cách sử dụng chế độ interactive trong Python

Cách sử dụng Python Debugger với hàm breakpoint()

Cách sử dụng Python Debugger với hàm breakpoint()

Xây dựng ứng dụng Web Style Transfer với PyTorch và Streamlit

Xây dựng ứng dụng Web Style Transfer với PyTorch và Streamlit

Cách cài đặt Jupyter Notebook trong môi trường Conda và thêm Kernel

Cách cài đặt Jupyter Notebook trong môi trường Conda và thêm Kernel

Hướng dẫn xây dựng ứng dụng dự đoán giá cổ phiếu bằng Python

Hướng dẫn xây dựng ứng dụng dự đoán giá cổ phiếu bằng Python

Hướng dẫn tạo ứng dụng AI hội thoại với NVIDIA Jarvis trong Python

Hướng dẫn tạo ứng dụng AI hội thoại với NVIDIA Jarvis trong Python

Hỗ trợ Async trong Django 3.1

Hỗ trợ Async trong Django 3.1

8 mẹo tái cấu trúc Python giúp mã sạch hơn và Pythonic

8 mẹo tái cấu trúc Python giúp mã sạch hơn và Pythonic

Ý nghĩa của if __name__ ==

Ý nghĩa của if __name__ == "__main__" trong Python

Cách xóa phần tử trong danh sách Python

Cách xóa phần tử trong danh sách Python

Top