- vừa được xem lúc

[Django ORM] Group By trong Django

0 0 27

Người đăng: Tùng Vũ

Theo Viblo Asia

Group by trong Django

Mình sẽ sử dụng User model đã hỗ trợ sẵn của Django nằm trong django.contrib.auth app.

Count

SQL:

SELECT COUNT(*) FROM auth_user

Django ORM:

User.objects.count()

Aggregate Function

Để sử dụng được các aggregate functions, chúng ta cần import các function đó nằm trong mục from django.db.models import Count.
Trong ví dụ này mình sẽ sử dụng Count function, ngoài ra còn cách aggregate function khác như: Max, Min, Sum, Avg.

SQL:

SELECT COUNT(id) AS id__count FROM auth_user

Django ORM:

from django.db.models import Count User.objects.aggregate(Count('id')) => {"id__count": 318}

Bạn cũng có thể thay đổi tên của giá trị trả về. Ví dụ mình sẽ đổi từ id__count sang total. SQL:

SELECT COUNT(id) AS total FROM auth_user

Django ORM:

from django.db.models import Count User.objects.aggregate(total=Count('id')) => {"total": 318}

Group by với aggregate function

SQL:

SELECT is_active, COUNT(id) AS total
FROM auth_user
GROUP BY is_active

Django ORM:

User.objects
.values('is_active')
.annotate(total=Count('id'))
  • values('is_active'): trường muốn group by.
  • annotate(total=Count('id')): group by theo aggregate function nào.

=> Thứ tự gọi là values trước annotate.

Filter a QuerySet với Group by

Ví dụ này sẽ đếm số lượng những user active hoặc inactive có role là staff.

SQL:

SELECT is_active, COUNT(id) AS total
FROM auth_user
WHERE is_staff = True
GROUP BY is_active

Django ORM:

User.objects
.values('is_active')
.filter(is_staff=True)
.annotate(total=Count('id'))

Sort a QuerySet với Group by

SQL:

SELECT is_active, COUNT(id) AS total
FROM auth_user
GROUP BY is_active
ORDER BY is_active, total

Django ORM:

User.objects
.values('is_active')
.annotate(total=Count('id'))
.order_by('is_active', 'total')

Kết hợp nhiều Aggregate Function với Group By

Ví dụ này sẽ đếm số lượng những user active hoặc inactive và với từng loại active hoặc inactive sẽ lấy ra last_joined.

SQL:

SELECT is_active, COUNT(id) AS total, MAX(date_joined) AS last_joined
FROM auth_user
GROUP BY is_active

Django ORM:

from django.db.models import Max User.objects
.values('is_active')
.annotate( total=Count('id'), last_joined=Max('date_joined'),
)

Group By nhiều trường

Kết quả của ví dụ này sẽ bao gồm is_active, is_staff và số lượng users với mỗi group.

SQL:

SELECT is_active, is_staff, COUNT(id) AS total
FROM auth_user
GROUP BY is_active, is_staff

Django ORM:

User.objects
.values('is_active', 'is_staff')
.annotate(total=Count('id'))

Group By với Expression

**SQL:**
SELECT EXTRACT('year' FROM date_joined), COUNT(id) AS total
FROM auth_user
GROUP BY EXTRACT('year' FROM date_joined)

Django ORM:

User.objects
.values('date_joined__year')
.annotate(total=Count('id'))

Sử dụng với Conditional Aggregation

**SQL:**
SELECT EXTRACT('year' FROM date_joined), COUNT(id) FILTER ( WHERE is_staff = True ) AS staff_users, COUNT(id) FILTER ( WHERE is_staff = False ) AS non_staff_users FROM auth_user
GROUP BY EXTRACT('year' FROM date_joined)

Django ORM:

from django.db.models import F, Q User.objects
.values('date_joined__year')
.annotate( staff_users=( Count('id', filter=Q(is_staff=True)) ), non_staff_users=( Count('id', filter=Q(is_staff=False)) ),
)

Sử dụng với Having

**SQL:**
SELECT is_active, COUNT(id) AS total
FROM auth_user
GROUP BY is_active
HAVING COUNT(id) > 100

Django ORM:

User.objects
.annotate(year_joined=F('date_joined__year'))
.values('is_active')
.annotate(total=Count('id'))
.filter(total__gt=100)

Distinct với Group By

**SQL:**
SELECT is_active, COUNT(id) AS total, COUNT(DISTINCT last_name) AS unique_names
FROM auth_user
GROUP BY is_active

Django ORM:

User.objects
.values('is_active')
.annotate( total=Count('id'), unique_names=Count('last_name', distinct=True),
)

Join với Group By

**SQL:**
SELECT p.type, COUNT(u.id) AS total
FROM auth_user u JOIN user_profile p ON u.id = p.user_id
GROUP BY p.type

Django ORM:

User.objects
.values('user_profile__type')
.annotate(total=Count('id'))

Group By với Many to Many Relationship

**SQL:**
SELECT u.id, COUNT(ug.group_id) AS memberships
FROM auth_user LEFT OUTER JOIN auth_user_groups ug ON ( u.id = ug.user_id )
GROUP BY u.id

Django ORM:

User.objects
.annotate(memberships=Count('groups'))
.values('id', 'memberships')

Hi vọng bài viết giúp ích được các bạn trong việc làm quen với Django ORM.

Mình có tham khảo và dịch lại bài viết tại blog:
https://hakibenita.com/django-group-by-sql

Bình luận

Bài viết tương tự

- vừa được xem lúc

Creating a Custom User Model in Django

Làm thế nào để thay thế username với email trong Django authentication. Cần chú ý rằng các làm này sẽ làm thay đổi rất nhiều đến schema của database vậy nên khuyến khích khi thực hiện một dự án mới.

0 0 23

- vừa được xem lúc

Câu chuyện kiểm soát truy cập trong Django.

Nếu bạn đang xây dựng một ứng dụng với Django, có thể bạn sẽ muốn kiểm soát quyền truy cập ứng với từng loại user. Những tính năng này sẽ phổ biến trên các trang web có quy mô lớn hơn một chút.

0 0 68

- vừa được xem lúc

Django: Handling CSV Data

Khi làm việc với các dự án Python hay Django thì phần xử lý CSV hầu như là không thể thiếu. Qua bài viết này, các bạn hãy cùng mình hiểu rõ hơn về CSV cũng như xử lý chúng ra sao nhé.

0 0 29

- vừa được xem lúc

Python Django - Xây dựng ứng dụng e-commerce (Part 1)

Giới thiệu Django - Khởi tạo project. Sơ qua về Django. . Django là một Framework lập trình web bậc cao được viết bằng ngôn ngữ lập trình Python.

0 0 856

- vừa được xem lúc

Deploy thủ công ứng dụng Django

Đối với một developer mà nói, mục đích cuối cùng của chúng ta khi phát triển một sản phẩm là có thể đưa sản phẩm ấy đến được với người dùng, và deploy là bước cuối cùng mà chúng ta cần thực hiện. Tron

0 0 259

- vừa được xem lúc

Dễ dàng có ngay ứng dụng e-commerce với Django (Part 2)

Xin chào tất cả mọi người. Tiếp nối bài viết trước về việc dùng Python Django để xây dựng 1 ứng dụng thương mại điện tử, sau đây mình xin phép được làm tiếp phần 2 để bổ sung thêm các chức năng, giúp

0 0 694