1. 程式人生 > >ORM的查詢

ORM的查詢

count str 對比 name python group 一個 django lex

基於對象的跨表查詢(sql裏的子查詢)(重點)

一對多查詢:

Book(有外鍵)--------------->Publish 屬於正向查詢 按book表裏的字段book.publish

Book(含外鍵)<---------------Publish 是反向查詢 按表名小寫_set.all()

正向查詢 例如:查python這本書的出版社的名字和郵箱

book=Book.objects.filter(title="python").first() #拿到對象, 對象.屬性才可以獲取值

print(book.publish.name)

print(book.publish.email)

反向查詢 例如:查蘋果出版社 出版的所有書籍的名字

pub_obj=Publish.objects.get(name="蘋果出版社")

print(pub_obj.book_set.all()) # print(pub_obj.book_set) 出版社找書, 因為出版過很多書,所以用 _set, .all()是找出所有的書

多對多查詢:

Book(有外鍵)--------------->Author 正向查詢 按book表裏的字段book.authors.all() 得到的是一個集合

Book(含外鍵)<---------------Publish 反向查詢 按表名小寫_set.all()

正向查詢 例如找python作者的年齡

book=Book.objects.filter(title="python").first() #拿到python這本書

ret = book.authors.all() # 拿到與這本書關聯的所有作者queryset

ret2 = book.authors.all().value("age")

print(ret2)

反向查詢 例如找alex出版過的書

alex=Author.objects.filter("name"="Alex").first() #獲取到alex對象 filter得到的是queryset .first()得到的是對象

print(alex.book_set.all())

一對一查詢

Author--------------->AuthorDetail 正向查詢 按字段 alex.ad(Author表裏的字段)

Author<---------------AuthorDetail 反向查詢 按表名 ad.author(表名)

正向查詢 例如:查詢alex的手機號

alex=Author.objects.filter("name"="alex").first()

print(alex.ad.tel)

反向查詢 例如:查手機號是110的用戶名

ad=AuthorDetail.objects.filter(tel=110).first()

print(ad.author.name)

-------------------------------------------------------------------------------------------------

雙下劃線的跨表查詢(基於sql中的join實現 ) (重點)

規則:正向查詢按字段 反向查詢按表名的小寫

不管以哪張表為基表, 寫在最前面的過濾條件是不變的, 變的是過濾條件的書寫方式, 就是按照上面的規則拼寫

一對多

例1: 查python的出版社的名字和郵箱

以Book為基表 從Book 往Publish方向找 是正向查詢

ret=Book.objects.filter(title="python").values("publish__name") #在values這開始跨表 告訴ORM的book表拼publish表

print(ret)

以Publish為基表 查出版python的出版社名字

ret=Publish.objects.filter(book__title="python").values("name")

#book__title="python" title不在基表Publish中 所以先拼表book(title字段在book中) 再反向拼表按表名小寫book__title

#values("name") name是基表Publish自己的字段可以直接使用

例2: 查蘋果出版社出版的所有的書的名字

以Book為基表 是正向查詢

ret=Book.objects.filter(pubish__name="蘋果出版社").values("title")

print(ret)

#蘋果出版社不在基表Book裏面,所以要先到Publish中把name="蘋果出版社"的過濾出來

#title是Book基表自己的字段

以Publish為基表 反向查詢

ret=Publish.objects.filter(name="蘋果出版社").values("book__title"")

print(ret)

#name="蘋果出版社" name在基表Pubish裏面,所以直接使用name字段

#title 不在基表Publish裏面, 所以要先找到Book表 (通過表名小寫的方式), 再__title

多對多

例1: 查python這本書作者的名字

以Book為基表 正查按字段

ret=Book.objects.filter(title="python").values("author__age")

print(ret)

#author Book拼關聯的author表 把三張表拼在一起

#title在基表Book裏面

以Author為基表

ret=Author.objects.filter(book__title="python").values("age")

print(ret)

例2: 查alex出版過的書

以Book表為基表

ret=Book.objects.filter(authors__name="alex").values("title")

print(ret) # [{ "title"=python }]

以Author表為基表

ret=Author.objects.filter(name="alex").values("book__title")

print(ret) # [{ "book__title"=python }] 對比一下兩種方式的查詢結果

一對一

例1: 查alex的tel

以Author為基表 正向查詢條件按字段

ret=Author.objects.filter(name="alex").values("ad__tel")

print(ret)

以AuthorDetail為基表

ret=AuthorDetail.objects.filter(authors__name="Alex").values("tel")

print(ret)

例2:手機號為110的作者的名字

以AuthorDetail為基表

ret=AuthorDetail.objects.filter(tel="110").values("author__name")

print(ret)

# tel在基表裏面,所以直接查詢.

# name不在基表裏面,所以要加表名小寫author__name

以Author為基表

ret=Author.objects.filter("ad__tel=110").values("name")

print(ret)

--------------------------------------------------------------------------------------------

連續跨表查詢

例1: 人民出版社出版過所有書的名稱以及作者的名字 (會用到Publish Book Author三張表)

以Publish為基表

ret=Publish.objects.filter(name="人民出版社").values("book__title","book__authors__name")

print(ret)

#name在基表的字段裏, title和name需要用所在的表名小寫連接起來再查詢

#站在基表的角度跨表

以Book為基表

ret=Book.objects.filter(publish__name="人民出版社").values("title","author__name")

print(ret)

例2: 以手機號110開頭的作者出版過的所有的 書的名稱以及出版社名稱(會用AD Author Book Publish四張表 )

以Author為基表

ret=Author.objects.filter(ad__tel__startswith=110).values("book__title","book__publish__name")

print(ret)

#沒有在基表裏的查詢字段都需要用加引號

------------------------------------------------------------------------------------------

聚合 分組查詢

from django.db.models import Avg, Sum, Max, Min, Count

聚合

例1: 查詢所有書籍的平均價

ret=Book.objects.all().aggregate(priceAvg=Avg("price"))

print(ret) #{"priceAvg":123}

例2: 查有多少本書

ret=Book.objects.all().aggreagte(c=Count("nid"))

print(ret) #{"c":4}

分組 以哪個字段分組 就把哪個字段放在values()裏

單表分組查詢

例1: 查詢Book表中每個出版社的id以及對應出版書的個數

ret=Book.objects.values("title").annotate()

#按照title分組的group by values裏面是分組的字段

例2: 求每個部門的平均工資

ret=Emp.objects.values("dep").annotate(avg_salary=Avg("salary"))

# 按部門分組 求平均工資

例3: 求每個出版社 出版的書的個數

ret=Book.objects.values("pubish__id").annotate(c=Count(1))

#publish__id是Book表裏的字段

print(ret)

#[{"publish_id":1, "c":2}, {"publish_id":2, "c":1}, {"publish_id":3, "c":1}]

跨表分組查詢 以哪個字段分組 就把哪個字段放在values()裏

例1: 查詢每個出版社名稱以及出版過的書的平均價格 查詢什麽 就以什麽為基表簡單點

ret=Publish.objects.values("nid").annotate(avg_price=Avg("book__price"))

# book__price拼表 按Publish表的nid分組

例2: 查詢每一個作者的名字以及出版過的書的最高價 查詢什麽 就以什麽為基表簡單點

ret=Author.objects.values("name").annotate(maxPrice=Max("book__price"))

# book__price去Book表找price

例3: 查詢每一個書名稱以及對應的作者的個數 (Book Author表)

ret=Book.objects.values("title").annotate(Count("authors")) ?????????

例4:

ret=Publish.objects.all().annotate(avg_price=Avg("book_price")).values("name","email","avg_price")

#前面的查詢結果 後面可以用????????????

例5: 查詢作者數不止一個的書名以及作者的個數 (重點看看)

ret=Book.objects.annotate(c=Count("authors").filter(c__gt=1).values("title","c"))

# c 添加到了Book對象的屬性中了

-------------------------------------------------------------------------

F和Q查詢:

F函數查詢

例1: 查詢評論數大於100的書名 以哪個字段分組 就把哪個字段放在values()裏

ret=Book.objects.filter(comment_count__gt=100).values("title")

例2: 評論數大於點贊數

from django.db.models. import F,Q (導入F Q函數)

ret=Book.objects.filter(comment_count__gt=F("poll_count"))

例3: 評論數大於2倍點贊數

ret=Book.objects.filter(comment_count__gt=F("poll_count")*2)

例4: 每本書的價格都在原價上加100

ret=Book.objects.all().update(price=100 + F("price"))

Q函數

例1: 查詢價格大於300或者評論數大於3000的書籍

ret=Book.objects.filter(Q(price__gt=300 | Q(comment_count__gt=3000)))

ORM的查詢