首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

Django ORM 中使用 Distinct 去重查詢的正確姿勢與 MySQL 相容性解析

     編輯:MySQL 綜合教學

Django ORM 中使用 Distinct 去重查詢的正確姿勢與 MySQL 相容性解析

在 Django 專案開發中,distinct() 是常用的去重查詢方法。然而,許多開發者在使用 MySQL 時會發現 distinct() 行為與 PostgreSQL 不同,甚至報錯。本文深入解析 Django ORM 中 distinct 的正確用法、MySQL 限制原因及解決方案。

一、Django 查詢的兩種主要方式

Django 提供兩種資料查詢途徑:

  1. ORM API 查詢:使用 filter()、values()、distinct()、order_by() 等模型方法
  2. 原始 SQL 查詢:使用 raw() 直接執行 SQL 語句

二、ORM API 中 distinct() 的正確用法

1. 基礎去重查詢

# 正確:查詢不重複的 finish_time
LOrder.objects.values('finish_time').distinct()

2. 搭配 order_by 使用(MySQL 必須)

MySQL 要求 DISTINCT 與 ORDER BY 欄位一致,因此需加上排序:

# MySQL 相容寫法
LOrder.objects.values('finish_time').distinct().order_by('finish_time')

3. 官方文檔範例與 MySQL 差異

Django 官方文檔範例多為 PostgreSQL 語法:

# PostgreSQL 支援指定欄位去重
Entry.objects.order_by('pub_date').distinct('pub_date')
Entry.objects.order_by('blog').distinct('blog')

關鍵差異:MySQL 不支援 distinct('field_name') 指定欄位去重語法,僅支援無參數的 distinct()。

三、原始 SQL 查詢方案

1. 使用 raw() 執行原生 SQL

LOrder.objects.raw('SELECT DISTINCT id, finish_time FROM keywork_lorder GROUP BY finish_time')

2. 兩大必須注意的坑

坑 1:主鍵不可省略
Django 要求原始查詢必須包含主鍵欄位(通常是 id),否則拋出 InvalidQuery 異常:
Raw query must include the primary key

坑 2:MySQL 去重需搭配 GROUP BY
MySQL 中 SELECT DISTINCT 實際執行邏輯等同於 GROUP BY,正確寫法:
SELECT DISTINCT id, finish_time FROM keywork_lorder GROUP BY finish_time

四、最佳實踐建議

場景推薦做法說明
單欄位去重.values('field').distinct().order_by('field')ORM 標準寫法,MySQL 相容
多欄位去重.values('field1','field2').distinct().order_by('field1','field2')所有 values 欄位需在 order_by 中
複雜去重邏輯使用 raw() + 原生 SQL包含主鍵,搭配 GROUP BY
大量資料去重考慮資料庫層面建立唯一索引從源頭避免重複資料

五、總結

  • MySQL 下使用 ORM distinct() 必須搭配 order_by()
  • 原始 SQL 查詢必須包含主鍵欄位
  • MySQL 的 DISTINCT 底層實際執行 GROUP BY 邏輯
  • 跨資料庫專案建議統一使用標準 ORM 寫法,避免原生 SQL 移植問題
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved