查找仅撰写历史书籍的作者

时间:2018-11-13 21:53:24

标签: sql

SQL的新手,尽管很流行-卡在该查询上。 这可行,尽管不应显示Paddy O'Furniture,因为该作者没有写过任何书,并且au_id也没有出现在title_authors表中。请帮忙。

查找仅撰写历史书籍的作者

select a.au_id, a.au_lname, a.au_fname

from authors a

where not exists(

    select ta.au_id

    from title_authors ta

    join titles t

    on t.title_id = ta.title_id

    where t.type != 'history'

    and a.au_id = ta.au_id

)

输出:

A01 Buchman Sarah

A07欧米茄稻草

3 个答案:

答案 0 :(得分:1)

Paddy O'Furniture出现在您的结果中,因为在相关子查询中未找到匹配的行。即该作者没有exist行,因此where not exists为真。

select a.au_id, a.au_lname, a.au_fname
from authors a
inner join title_authors ta ON a.au_id = ta.au_id
inner join titles t on ta.title_id = t.title_id
group by a.au_id, a.au_lname, a.au_fname
having count(case when t.type <> 'history' then 1 end) = 0

以上方法在count()函数中使用了case表达式,因此,如果任何书籍具有非历史记录类型,则此计数将大于零。 having子句允许使用聚合值来过滤最终结果(在group by子句之后使用,不能代替where子句)。

答案 1 :(得分:0)

您很近。在外部查询的JOIN上添加title_authors会过滤掉尚未写书的作者。

select a.au_id, a.au_lname, a.au_fname
from authors a
join title_authors ta1 on ta1.au_id = a.au_id
where not exists(
    select 1
    from title_authors ta
    join titles t on t.title_id = ta.title_id
    where t.type != 'history' and ta1.id = ta.id
)

内部查询中的title_authors实际上可以删除。

select a.au_id, a.au_lname, a.au_fname
from authors a
join title_authors ta on ta.au_id = a.au_id
where not exists(
    select 1
    from titles
    where t.type != 'history' and title_id = ta.title_id
)

答案 2 :(得分:0)

虽然如果您使用另一个exists来确保作者至少写了一本历史书,那么您的方法也可以使用,但是这是使用conditional aggregation的另一种方法:

select a.au_id, a.au_lname, a.au_fname
from authors a
    join title_authors ta on a.au_id = ta.au_id
    join titles t on ta.title_id = t.title_id
group by a.au_id, a.au_lname, a.au_fname
having sum(case when t.type != 'history' then 1 else 0 end) = 0

Online Demo