如何select多对多的一对一关系table
How to select one to one relations from many to many table
我有一个数据库,用于保存书籍及其作者。在我的模型中,一位作者可以拥有多本书,而一本书可以由多位作者撰写。示例:
AUTHOR_ID|BOOK_ID
1|100
1|200
1|300
2|300
3|300
4|400
我试图找到只写过一本书的作者,并且那本书必须仅由该作者单独撰写。在上面的例子中,只有有效的作者是 AUTHOR_ID = 4.
我需要写一个 select 来获取满足上述要求的作者 ID,我怎样才能快速高效地写 select 来做到这一点?
select *
from BookAuthors t1
where not exists (select * from BookAuthors t2
where t2.BOOK_ID = t1.BOOK_ID
and t2.Author_ID <> t1.Author_ID)
and not exists (select * from BookAuthors t3
where t3.Author_ID = t1.Author_ID
and t3.BOOK_ID <> t1.BOOK_ID)
第一个 NOT EXISTS
是为了确保同一个 bookid 没有第二个作者。
第二个 NOT EXISTS
是为了确保 Author_ID 没有写过另一本书。
合并版本:
select *
from BookAuthors t1
where not exists (select * from BookAuthors t2
where (t2.BOOK_ID = t1.BOOK_ID
and t2.Author_ID <> t1.Author_ID)
or (t2.Author_ID = t1.Author_ID
and t2.BOOK_ID <> t1.BOOK_ID))
这是一个单独的答案,因为第一个答案是错误的。
如果您的数据库支持 window 函数,一种方法是:
select Author_ID
from (select ba.*, count(*) over (partition by Author_ID) as numBooks,
count(*) over (partition by Book_ID) as numAuthors
from BookAuthors ba
) ba
where numBooks = 1 and numAuthors = 1;
还有多种方法可以将条件移动到 where
子句或 join
s:
select ba.*
from BookAuthors ba
where Author_ID in (select Author_Id from BookAuthors group by Author_Id having count(*) = 1) and
Book_ID in (select Author_Id from BookAuthors group by Book_ID having count(*) = 1);
我有一个数据库,用于保存书籍及其作者。在我的模型中,一位作者可以拥有多本书,而一本书可以由多位作者撰写。示例:
AUTHOR_ID|BOOK_ID
1|100
1|200
1|300
2|300
3|300
4|400
我试图找到只写过一本书的作者,并且那本书必须仅由该作者单独撰写。在上面的例子中,只有有效的作者是 AUTHOR_ID = 4.
我需要写一个 select 来获取满足上述要求的作者 ID,我怎样才能快速高效地写 select 来做到这一点?
select *
from BookAuthors t1
where not exists (select * from BookAuthors t2
where t2.BOOK_ID = t1.BOOK_ID
and t2.Author_ID <> t1.Author_ID)
and not exists (select * from BookAuthors t3
where t3.Author_ID = t1.Author_ID
and t3.BOOK_ID <> t1.BOOK_ID)
第一个 NOT EXISTS
是为了确保同一个 bookid 没有第二个作者。
第二个 NOT EXISTS
是为了确保 Author_ID 没有写过另一本书。
合并版本:
select *
from BookAuthors t1
where not exists (select * from BookAuthors t2
where (t2.BOOK_ID = t1.BOOK_ID
and t2.Author_ID <> t1.Author_ID)
or (t2.Author_ID = t1.Author_ID
and t2.BOOK_ID <> t1.BOOK_ID))
这是一个单独的答案,因为第一个答案是错误的。
如果您的数据库支持 window 函数,一种方法是:
select Author_ID
from (select ba.*, count(*) over (partition by Author_ID) as numBooks,
count(*) over (partition by Book_ID) as numAuthors
from BookAuthors ba
) ba
where numBooks = 1 and numAuthors = 1;
还有多种方法可以将条件移动到 where
子句或 join
s:
select ba.*
from BookAuthors ba
where Author_ID in (select Author_Id from BookAuthors group by Author_Id having count(*) = 1) and
Book_ID in (select Author_Id from BookAuthors group by Book_ID having count(*) = 1);