查找所有共同作者 - Faceting/Grouping 用于多对多映射 table
Find all co authors - Faceting/Grouping for many to many mapping table
Table : Books
-------------
ID Name
1 Book1
2 Book2
3 Book3
4 Book4
Table : Authors
-------------
ID Name
1 Author1
2 Author2
3 Author3
4 Author4
Table : BookAuthorMapping
---------------------------
ID BookId AuthorId
1 1 1
2 1 2
3 1 3
4 2 2
5 2 3
6 3 3
7 4 4
所以,
- Book1 由 Author1,Author2,Author3 撰写
- Book2 由 Author2,Author3 撰写
- Book3 仅由作者 3 撰写
- Book4 仅由作者 4 撰写
问题是:
给定一个 AuthorId,我需要找出其他作者与他合着了多少本书:
示例:
Given AuthorId: 1
-------------------
AuthorId Count
2 1 // 2 has co-authored only book1
3 1 // 3 has co-authored only book1
1 1 // Its okay, if i get author1 in the result
Given AuthorId: 2
-------------------
AuthorId Count
1 1 // 1 has co-authored only book1
3 2 // 3 has co-authored book1 and book2
2 2 // Its okay if i get author 2 in the result
Given AuthorId: 3
-------------------
AuthorId Count
1 1 // 1 has co-authored only book1
2 2 // 2 has co-authored book1 and 2
3 3 // Its okay if i get author 3 in the result.
Given AuthorId: 4
-------------------
AuthorId Count
4 1 // I should not get author1 0 author2 0 , author3 0 for this
-- 编辑 --
我有一个像这样的解决方案:select aId, count(mapping.bId) from mapping join (select bId from mapping where aId = ?) as tmp on mapping.bId = tmp.bId group by aId;
此外,@Giorgos Betsos 在回复中也提到了同样的问题。
我很好奇如果没有内部查询是否可行。
试试这个:
SELECT "AuthorId", COUNT(*)
FROM BookAuthorMapping
WHERE "BookId" IN (SELECT "BookId" FROM BookAuthorMapping WHERE "AuthorId" = 1)
GROUP BY "AuthorId"
您也可以使用 INNER JOIN
:
SELECT t1."AuthorId", COUNT(*)
FROM BookAuthorMapping AS t1
INNER JOIN BookAuthorMapping AS t2 ON t1."BookId" = t2."BookId" AND t2."AuthorId" = 1
GROUP BY t1."AuthorId"
您也可以使用 window 函数执行此操作:
select authorid, count(*)
from (select bam.*,
max(case when AuthorId = 1 then 1 else 0 end) over (partition by bookid) as HasAuthor1
from BookAuthorMapping bam
) bam
where hasAuthor1 = 1
group by authorid;
在某些情况下,window 函数比使用 join
或 in
的方法更快。
Table : Books
-------------
ID Name
1 Book1
2 Book2
3 Book3
4 Book4
Table : Authors
-------------
ID Name
1 Author1
2 Author2
3 Author3
4 Author4
Table : BookAuthorMapping
---------------------------
ID BookId AuthorId
1 1 1
2 1 2
3 1 3
4 2 2
5 2 3
6 3 3
7 4 4
所以,
- Book1 由 Author1,Author2,Author3 撰写
- Book2 由 Author2,Author3 撰写
- Book3 仅由作者 3 撰写
- Book4 仅由作者 4 撰写
问题是: 给定一个 AuthorId,我需要找出其他作者与他合着了多少本书:
示例:
Given AuthorId: 1
-------------------
AuthorId Count
2 1 // 2 has co-authored only book1
3 1 // 3 has co-authored only book1
1 1 // Its okay, if i get author1 in the result
Given AuthorId: 2
-------------------
AuthorId Count
1 1 // 1 has co-authored only book1
3 2 // 3 has co-authored book1 and book2
2 2 // Its okay if i get author 2 in the result
Given AuthorId: 3
-------------------
AuthorId Count
1 1 // 1 has co-authored only book1
2 2 // 2 has co-authored book1 and 2
3 3 // Its okay if i get author 3 in the result.
Given AuthorId: 4
-------------------
AuthorId Count
4 1 // I should not get author1 0 author2 0 , author3 0 for this
-- 编辑 --
我有一个像这样的解决方案:select aId, count(mapping.bId) from mapping join (select bId from mapping where aId = ?) as tmp on mapping.bId = tmp.bId group by aId;
此外,@Giorgos Betsos 在回复中也提到了同样的问题。
我很好奇如果没有内部查询是否可行。
试试这个:
SELECT "AuthorId", COUNT(*)
FROM BookAuthorMapping
WHERE "BookId" IN (SELECT "BookId" FROM BookAuthorMapping WHERE "AuthorId" = 1)
GROUP BY "AuthorId"
您也可以使用 INNER JOIN
:
SELECT t1."AuthorId", COUNT(*)
FROM BookAuthorMapping AS t1
INNER JOIN BookAuthorMapping AS t2 ON t1."BookId" = t2."BookId" AND t2."AuthorId" = 1
GROUP BY t1."AuthorId"
您也可以使用 window 函数执行此操作:
select authorid, count(*)
from (select bam.*,
max(case when AuthorId = 1 then 1 else 0 end) over (partition by bookid) as HasAuthor1
from BookAuthorMapping bam
) bam
where hasAuthor1 = 1
group by authorid;
在某些情况下,window 函数比使用 join
或 in
的方法更快。