|
我有以下结构:5 }2 i' W" {4 D" i7 Z9 m! W
CREATE TABLE author id integer ,name varchar(255));CREATE TABLE book id integer ,author_id integer ,title varchar(255) ,rating integer);我希望每个作者都能读到最后一本书:
2 d# S, k* E2 D1 B; M7 zSELECT book.id,author.id,author.name,book.title as last_bookFROM authorJOIN book book ON book.author_id = author.idGROUP BY author.idORDER BY book.id ASC显然,你可以在那里mysql执行此操作:在MySQL连接两个表,只从第二个表返回一行。/ b( |7 y( M. d/ T
但是postgres给出这个错误:! i; m( F K+ ^% B2 U. x
错误:“ book.id必须出现列GROUP BY用于子句或聚合函数:SELECT) j3 l) y' {7 d3 W6 K5 f
book.id,author.id,author.name,book.title为last_book FROM author JOIN book1 Y* r8 V/ S8 E0 }& y: y' t/ j8 s
book on book.author_id = author.id GROUP BY author.id ORDER BY book.id ASC; z) A7 j( n* q* g: Q
这是因为:
0 P) r0 a6 g. Q7 ~3 Y9 j9 A* X如果存在GROUP BY,则SELECT未分组列(聚合函数除外)不能引用列表表达式,因为未分组列将返回多个可能值。
5 v8 t) d! p- [. b0 v5 L/ x% E我如何指定postgres:“仅joined_table.id在连接表中按顺序给我最后一行?$ e4 n3 X) e* |: l4 o Q
编辑:使用此数据: |+ _" Z; i* a- H
INSERT INTO author (id,name) VALUES (1,'Bob(二),David(3),John');INSERT INTO book (id,author_id,title,rating) VALUES 1、1、1、1st book from bob五、nd book from bob六、rd book from bob七、st book from David(、nd book from David',6);我应该看到:
0 d5 @6 M( B# \ a. t+ gbook_id author_id name last_book3 3 1 "Bob" "3rd book from bob"5 2 "David" "2nd book from David" 9 a* j5 s: G- K7 m- W9 g# m; _9 h7 U
解决方案: @5 _- J3 z! M, [ t# \' R
select distinct on (author.id) book.id,author.id,author.name,book.title as last_bookfrom author inner join book on book.author_id = author.idorder by author.id,book.id desc查看 distinct on
0 P$ U+ ?5 v6 {% O9 XSELECT DISTINCT ON(expression [,…])每组行的第一行只保留给定表达式。ORDER+ l* s& U* ?$ |2 j5 H
BY解释相同的规则DISTINCT ON表达式(请参见上面)。请注意,除非使用。ORDER
- P; Z: x* H0 j1 l: D; z2 \7 `BY确保所需的行先出现,否则每一集的第一行都是不可预测的。: U: l2 V7 w" }9 I2 G7 L6 T1 a5 h
内容独特,有必要在其中添加独特列order by。如果不是你想要的顺序,你需要包装查询并重新排序
+ g5 t, j* F8 N- Aselect *from select distinct on (author.id) book.id,author.id,author.name,book.title as last_book from author inner join book on book.author_id = author.id order by author.id,book.id desc) authors_with_first_bookorder by authors_with_first_book.name另一种解决方案是使用Lennart答案中的窗口函数。另一个很常见的是
+ D, M! g: }5 o% {2 p3 a) D2 Xselect book.id,author.id,author.name,book.title as last_bookfrom book inner join ( select author.id as author_id,max(book.id) as book_id from author inner join book on author.id = book.author_id group by author.id ) s on s.book_id = book.id inner join author on book.author_id = author.id |
|