Как выбрать самое старое значение в кортеже - PullRequest
0 голосов
/ 29 октября 2018

Я использую sqlplus в Oracle, и мой вопрос:

  • Найдите идентификатор книги, название, автора и год публикации книги, у которой самый старый год публикации.
  • Тогда найдите имя автора (ов), у которого наибольшее количество разных книг, принадлежащих библиотека (несколько экземпляров одной книги считаются только одной книгой).

Вот моя база данных:

 drop table history;
 drop table currentloan;
 drop table member;
 drop table book;

 /*
    creates table with 6 variables
    assigns one primary key
    uses different data types for different cases
 */  

create table Book
(bookID             number(12) Primary Key,
 ISBN               number(13),
 title              varchar(50),
 author             varchar(20),
 publish_year       number(4),
 category           char(11));

 /*
    Inserts tuples with matching variables 
    uses different book categories for testing purposes  
 */ 

insert into Book values('7839494', '9780143122784', 'Guitar Zero', 'Gary Marcus', '2012', 'non-fiction');
insert into Book values('7839495', '9780143122784', 'Guitar Zero', 'Gary Marcus', '2012', 'non-fiction');
insert into Book values('7839496', '9780143122784', 'Guitar Zero', 'Gary Marcus', '2012', 'non-fiction');
insert into Book values('1405904', '9780071812436', 'Oracle Database 12c PL/SQL Programming', 'Michael McLaughlin', '2014', 'reference');
insert into Book values('9890304', '9781449343033', 'Oracle Essentials: Oracle Database 12c', 'Rick Greenwald', '2013', 'reference');
insert into Book values('1893409', '9781598635034', 'Music Theory for Computer Musicians', 'Michael Hewitt', '2008', 'non-fiction');
insert into Book values('3848598', '9781119247791', 'Java All-in-One For Dummies', 'Doug Lowe', '2017', 'non-fiction');
insert into Book values('3848599', '9781119247791', 'Java All-in-One For Dummies', 'Doug Lowe', '2017', 'non-fiction');
insert into Book values('3049891', '9780679805274', 'Oh, the Places Youll Go', 'Dr. Seuss', '1990', 'Childrens');
insert into Book values('3049892', '9780679805274', 'Oh, the Places Youll Go', 'Dr. Seuss', '1990', 'Childrens');
insert into Book values('3049893', '9780679805274', 'Oh, the Places Youll Go', 'Dr. Seuss', '1990', 'Childrens');
insert into Book values('9839209', '9780072465631', 'Database Management Systems', 'Raghu Ramakrishnan', '2008', 'reference');
insert into Book values('3234567', '9780316605106', 'Cirque du Freak: A Living Nightmare', 'Darren Shan', '2002', 'fiction');
insert into Book values('3234568', '9780316605106', 'Cirque du Freak: A Living Nightmare', 'Darren Shan', '2002', 'fiction');
insert into Book values('3234569', '9780316605106', 'Cirque du Freak: A Living Nightmare', 'Darren Shan', '2002', 'fiction');
insert into Book values('3234570', '9780316605106', 'Cirque du Freak: A Living Nightmare', 'Darren Shan', '2002', 'fiction');
insert into Book values('1239480', '9781421539645', 'DeathNote Black Edition Vol. 1', 'Tsugumi Ohba', '2010', 'fiction');
insert into Book values('5467878', '9780877798095', 'Merriam_Websters Collegiate Dictionary', 'Merriam_Webster', '2003', 'reference');
insert into Book values('5467879', '9780877798095', 'Merriam_Websters Collegiate Dictionary', 'Merriam_Webster', '2003', 'reference');
commit;

 /*
    Creates member table with 6 variables 
    assigns one primary key 
    uses not null to ensure efficiency
  */ 
create table Member
(memberID            number(15) Primary Key,
 lastname            char(15),
 firstname           char(15) not null,
 address             varchar(30),
 phone_number        number(10),
 limit               number(3));


 /*
    Uses insert to fill member table with values 
    ensures values differ for testing  
*/

insert into Member values ('00986845', 'Guevara', 'Merlyn', '9705 hardwood ln', '9806369324', '5');
insert into Member values ('00425663', 'Courtney', 'Kacey', '1520 glengarry dr', '9848339522', '5');
insert into Member values ('00327889',  'Wells', 'Trey', '650 zack rd', '9802428333', '5');
insert into Member values ('00546283', 'Lopez', 'Manny', '123 Road st', '7046368300', '10');
insert into Member values ('00728432', 'Mondragon', 'Alpha', '6100 Raven peak dr', '7043028422', '5'); 
insert into Member values ('00345674', 'Jones', 'David', '4321 Rowan Way', '9803334564', '7');
insert into Member values ('00456742', 'Smith', 'John', '3456 Circle Pl', '7043239098', '8');
commit;


  /*    Generates table to track books checked out 
        Initializes 4 different variables
 */
create table CurrentLoan
( memberID           number(15),
  bookID             number(12),
  loan_date          varchar(10),
  due_date           varchar(10),
  FOREIGN KEY(bookID) REFERENCES book(bookID),
  Foreign key(memberID) REFERENCES member(memberID));


 /*
    uses insert to add currently checked out books  
*/

insert into Currentloan values('00986845', '7839494', '09/28/2018', '12/28/2018');
insert into Currentloan values('00546283', '1405904', '08/12/2018', '11/12/2018');
insert into Currentloan values('00327889', '9839209', '09/05/2018', '12/05/2018');
insert into Currentloan values('00345674', '1239480', '08/04/2018', '10/12/2018');
insert into Currentloan values('00456742', '1893409', '07/04/2018', '10/04/2018');
insert into Currentloan values('00456742', '5467878', '07/05/2018', '10/05/2018');
insert into Currentloan values('00456742', '7839496', '07/05/2018', '10/05/2018');
insert into Currentloan values('00456742', '3848599', '07/05/2018', '10/05/2018');
insert into Currentloan values('00456742', '3049892', '07/05/2018', '10/05/2018');
insert into Currentloan values('00456742', '3234569', '07/05/2018', '10/05/2018');
insert into Currentloan Values('00986845', '3234568', '08/02/2018', '11/02/2018');
insert into Currentloan Values('00986845', '3049891', '08/02/2018', '11/02/2018');
insert into Currentloan Values('00986845', '3848598', '08/02/2018', '11/02/2018');
insert into Currentloan Values('00986845', '5467879', '08/02/2018', '11/02/2018');
insert into Currentloan Values('00986845', '3234570', '08/02/2018', '11/02/2018');
commit;


 /*     Generates table of books checked out in the past
     Initializes 4 variables 
    deterines primary and foreign keys
 */
create table History
(memberID            number(15),
 bookID              number(12),
 loan_date           varchar(10) Primary Key,
 return_date         varchar(10),
 Foreign Key(bookID) References book(bookID),
 Foreign Key(memberID) References member(memberID));
 /*
    uses insert to specify previously checked out books. 
 */
insert into History values ('00728432', '5467878', '02/08/2017', '04/05/2017');
insert into History values ('00986845', '3234567', '09/12/2017', '10/10/2017');
insert into History values ('00728432', '3848598', '07/14/2016', '09/04/2017');
insert into History values ('00986845', '1239480', '11/14/2016', '01/26/2017');
insert into History values ('00456742', '3234569', '07/05/2016', '09/02/2016');
commit;

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

Select bookID, title, author, publish_yea, Min(publish_year)
from Book 
group by bookID
having publish_year = Min(publish_year);

Ответы [ 3 ]

0 голосов
/ 29 октября 2018

Я бы ожидал сообщение об ошибке ORA-00979: not a GROUP BY expression из вашего запроса. Вам не хватает трех имен столбцов в предложении group by, чтобы избежать этой ошибки, оно должно выглядеть следующим образом:

Select bookID, title, author, publish_year, Min(publish_year)
from Book 
group by bookID <b>, TITLE, AUTHOR, PUBLISH_YEAR</b>
having publish_year = Min(publish_year);

НО , этот запрос не даст того, что вы ищете. Вы группируете по уникальному значению (первичному ключу), поэтому вы получаете все строки таблицы, возвращаемые этим запросом.

Select bookID, title, author, publish_year, Min(publish_year)
from Book 
group by bookID, title, author, publish_year
having publish_year = Min(publish_year)
BOOKID  | TITLE                                  | AUTHOR             | PUBLISH_YEAR | MIN(PUBLISH_YEAR)
:------ | :------------------------------------- | :----------------- | :----------- | :----------------
1893409 | Music Theory for Computer Musicians    | Michael Hewitt     | 2008         | 2008             
3848598 | Java All-in-One For Dummies            | Doug Lowe          | 2017         | 2017             
3234567 | Cirque du Freak: A Living Nightmare    | Darren Shan        | 2002         | 2002             
7839495 | Guitar Zero                            | Gary Marcus        | 2012         | 2012             
3049891 | Oh, the Places Youll Go                | Dr. Seuss          | 1990         | 1990             
3049893 | Oh, the Places Youll Go                | Dr. Seuss          | 1990         | 1990             
7839496 | Guitar Zero                            | Gary Marcus        | 2012         | 2012             
3234568 | Cirque du Freak: A Living Nightmare    | Darren Shan        | 2002         | 2002             
5467878 | Merriam_Websters Collegiate Dictionary | Merriam_Webster    | 2003         | 2003             
3049892 | Oh, the Places Youll Go                | Dr. Seuss          | 1990         | 1990             
1239480 | DeathNote Black Edition Vol. 1         | Tsugumi Ohba       | 2010         | 2010             
9890304 | Oracle Essentials: Oracle Database 12c | Rick Greenwald     | 2013         | 2013             
3848599 | Java All-in-One For Dummies            | Doug Lowe          | 2017         | 2017             
7839494 | Guitar Zero                            | Gary Marcus        | 2012         | 2012             
3234570 | Cirque du Freak: A Living Nightmare    | Darren Shan        | 2002         | 2002             
5467879 | Merriam_Websters Collegiate Dictionary | Merriam_Webster    | 2003         | 2003             
1405904 | Oracle Database 12c PL/SQL Programming | Michael McLaughlin | 2014         | 2014             
9839209 | Database Management Systems            | Raghu Ramakrishnan | 2008         | 2008             
3234569 | Cirque du Freak: A Living Nightmare    | Darren Shan        | 2002         | 2002             

Как сообщает Turbero, подзапрос для самого раннего глобального года будет работать:

select bookID, title, author, publish_year
from Book
WHERE publish_year = (SELECT min(publish_year) FROM Book) 
BOOKID  | TITLE                   | AUTHOR    | PUBLISH_YEAR
:------ | :---------------------- | :-------- | :-----------
3049891 | Oh, the Places Youll Go | Dr. Seuss | 1990        
3049892 | Oh, the Places Youll Go | Dr. Seuss | 1990        
3049893 | Oh, the Places Youll Go | Dr. Seuss | 1990        

ИЛИ, и альтернативой может быть использование оконной функции rank() (или dense_rank())

select  bookID, title, author, publish_year
from (
      select  bookID, title, author, publish_year
         , rank() over(order by publish_year) rnk
      from book
     ) d
where rnk = 1
BOOKID  | TITLE                   | AUTHOR    | PUBLISH_YEAR
:------ | :---------------------- | :-------- | :-----------
3049891 | Oh, the Places Youll Go | Dr. Seuss | 1990        
3049893 | Oh, the Places Youll Go | Dr. Seuss | 1990        
3049892 | Oh, the Places Youll Go | Dr. Seuss | 1990        

См. Все вышеупомянутые запросы онлайн здесь db <> fiddle здесь

0 голосов
/ 29 октября 2018

В Oracle 12C + вы можете использовать fetch first. Предполагая, что вы хотите только одну строку:

Select bookID, title, author, publish_yea, publish_year
from Book 
order by publish_year desc
fetch first 1 rows only;

В более ранних версиях решение rank(), представленное в другом ответе, является, вероятно, лучшим подходом.

0 голосов
/ 29 октября 2018

В вашем выборе есть небольшая опечатка "publish_yea".

Я предварительно загрузил вашу базу данных в https://sqliteonline.com/ и затем запустил ваш запрос с исправленной опечаткой:

select bookID, title, author, publish_year, Min(publish_year)
from Book 
group by bookID
having publish_year = Min(publish_year);

Это сработало.

Но этот запрос дает вам минимальный год публикации каждой группы, а не глобальный мин. Этот запрос сделает это:

select bookID, title, author, publish_year
from Book
WHERE publish_year = (SELECT min(publish_year) FROM Book) 
...