Попытка написать запрос, который отображает имена всех авторов, которые опубликовали статьи в течение двух лет подряд - PullRequest
0 голосов
/ 03 мая 2020

База данных, в которой хранится информация об авторе и публикации, имеет следующую схему:

CREATE TABLE Author (aid integer NOT NULL,
name varchar(50) NOT NULL,
affiliation varchar(50), primary key(aid));

CREATE TABLE Paper (pid  integer NOT NULL,
title varchar(50) NOT NULL,
year integer NOT NULL, primary key(pid));

CREATE TABLE Authored (aid integer references Author,
pid integer references Paper,
primary key(aid, pid), foreign key(aid) references Author(aid), foreign key(pid) references Paper(pid));

insert into Author(aid, name, affiliation) values (1, "A", "DS");
insert into Author(aid, name, affiliation) values (2, "B", "PS");
insert into Author(aid, name, affiliation) values (3, "C", "CS");

insert into Paper(pid, title, year) values (100, "DS1", 2019);
insert into Paper(pid, title, year) values (101, "PS1", 2019);
insert into Paper(pid, title, year) values (102, "CS1", 2019);
insert into Paper(pid, title, year) values (103, "DS2", 2020);
insert into Paper(pid, title, year) values (104, "PS2", 2020);
insert into Paper(pid, title, year) values (105, "CS2", 2019);

Authored.aid - это внешний ключ для Author, а Authored.pid - это внешний ключ для Paper.

Я пытаюсь написать запрос, который печатает имена всех авторов, которые публиковали статьи в течение двух лет подряд. Вот то, что я имею до сих пор, но это кажется слишком сложным.

select au1.aid as id, a1.name as name
from authored au1 
inner join authored au2 on au1.aid = au2.aid
inner join author a1 on au1.aid = a1.aid
inner join paper p1 on au1.pid = p1.pid
inner join paper p2 on au2.pid = p2.pid
where p1.year = p2.year + 1
order by au1.aid;

Ответы [ 3 ]

0 голосов
/ 03 мая 2020

Не кажется, что это сложно

SELECT au1.aid as id, au1.name AS name
FROM author au1 INNER join authored authored1 ON au1.aid=authored1.aid
INNER join paper p1 ON authored1.pid=p1.pid
WHERE au1.aid IN (SELECT au2.aid FROM author au2 
                  INNER join authored authored2 ON au1.aid=authored2.aid
                  INNER join paper p2 ON au2.pid=p1.pid AND  p2.year = p1.year+1)
ORDER by au1.aid;

Вы также можете использовать SQL EXISTS вместо IN

0 голосов
/ 03 мая 2020

Я бы использовал lag(). Чтобы получить идентификаторы автора:

select p.aid
from (select a.aid, p.year,
             lag(p.year) over (partition by a.aid order by p.year) as prev_year
      from papers p join
           authored a
           on a.pid = p.pid
      group by a.aid, p.year
     ) p
where prev_year = year - 1

Затем вы можете использовать in или join или что угодно, чтобы получить полную информацию об авторе:

select a.*
from authors a
where a.aid in (select a.aid
                from (select a.aid, p.year, 
                             lag(p.year) over (partition by a.aid order by p.year) as prev_year
                      from papers p join
                           authored a
                           on p.pid = a.pid
                      group by a.aid, p.year
                     ) p
                where prev_year = year - 1
               );

Вам на самом деле не нужно отставание, но это, вероятно, будет гораздо более эффективным. Альтернатива:

with pa as (
      select p.*, a.aid
      from papers p join
           authors a
           on p.pid = p.pid
     )
select a.*
from authors a
where a.aid in (select p.aid
                from pa p join
                     pa p_prev
                     on p_prev.aid = p.aid and
                        p_prev.year = p.year - 1
               );
0 голосов
/ 03 мая 2020

Попробуйте следующее, похоже, пробелы и проблема острова. Вот небольшой пример demo , который даст вам представление о том, как решить вашу проблему.

select
    id,
    name
from
(
    select
        aid,
        name,
        count(*) over (partition by rnk) as total
    from
    (
        select 
            aid as id, 
            name,
            year - row_number() over (partition by aid, name order by year) as rnk
        from authored au            

        inner join author a
        on au.aid = a.aid

        inner join paper p
        on au.pid = p.pid
    ) val
) fin
where total = 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...