Оставленное внешнее соединение и счет в Oracle - PullRequest
0 голосов
/ 10 февраля 2019

У моего преподавателя есть вопросы ниже. 7) Музей запрашивает имена и фамилии всех археологов, а также количество мест, где они обнаружили динозавров Tyrannosaurus Rex.Обратите внимание, что некоторые археологи не нашли никаких динозавров, а некоторые не нашли никаких динозавров Tyrannosaurus Rex, но все же должны быть включены в список.,Может кто-нибудь помочь с тем, как я могу включить всю информацию из вопроса?

 SELECT ARCHEOLOGIST.FIRST_NAME, ARCHEOLOGIST.LAST_NAME,DINOSAUR.DINO_NAME, LOCATION.LOCATION_ID,
  COUNT(LOCATION.LOCATION_ID)AS TOTAL_LOCATIONS
FROM ARCHEOLOGIST
LEFT OUTER JOIN DISCOVERY ON DISCOVERY.ARCH_ID = ARCHEOLOGIST.ARCH_ID
LEFT OUTER JOIN LOCATION ON LOCATION.LOCATION_ID = DISCOVERY.LOCATION_ID
LEFT OUTER JOIN DINOSAUR ON DISCOVERY.DINO_ID = DINOSAUR.DINO_ID
WHERE (DISCOVERY.DINO_ID = 123) 
group by ARCHEOLOGIST.FIRST_NAME, ARCHEOLOGIST.LAST_NAME, DINOSAUR.DINO_NAME, LOCATION.LOCATION_ID;

CREATE TABLE DINOSAUR
(DINO_ID NUMBER(3) PRIMARY KEY,
DINO_NAME VARCHAR2(50) NOT NULL,
DIET_TYPE VARCHAR2(25) NOT NULL,
COST NUMBER(10));

CREATE TABLE LOCATION
(LOCATION_ID VARCHAR2(2) PRIMARY KEY,
LOCATION_NAME VARCHAR2(50) NOT NULL,
STATE_NAME VARCHAR2(50) NOT NULL);

CREATE TABLE ARCHEOLOGIST
(ARCH_ID VARCHAR2(3) PRIMARY KEY,
FIRST_NAME VARCHAR2(25) NOT NULL,
LAST_NAME VARCHAR2(25) NOT NULL);

CREATE TABLE DISCOVERY
(DISC_ID VARCHAR2(3) PRIMARY KEY,
DISC_DATE DATE NOT NULL,
DINO_ID NUMBER(3) NOT NULL,
ARCH_ID VARCHAR2(3) NOT NULL,
LOCATION_ID VARCHAR2(2) NOT NULL);

ALTER TABLE DISCOVERY
ADD CONSTRAINT DINO_ID
FOREIGN KEY (DINO_ID)
REFERENCES DINOSAUR(DINO_ID);

ALTER TABLE DISCOVERY
ADD CONSTRAINT ARCH_ID
FOREIGN KEY (ARCH_ID)
REFERENCES ARCHEOLOGIST(ARCH_ID);

ALTER TABLE DISCOVERY
ADD CONSTRAINT LOCATION_ID
FOREIGN KEY (LOCATION_ID)
REFERENCES LOCATION(LOCATION_ID);

INSERT INTO DINOSAUR
(DINO_ID, DINO_NAME, DIET_TYPE, COST)
VALUES
(123,'TYRANNOSAURUS REX','CARNIVORE',100000);

INSERT INTO DINOSAUR
(DINO_ID, DINO_NAME, DIET_TYPE, COST)
VALUES
(234,'TYRANNOSAURUS REX','CARNIVORE',500000);

INSERT INTO DINOSAUR
(DINO_ID, DINO_NAME, DIET_TYPE, COST)
VALUES
(345,'TYRANNOSAURUS REX','HERBIVORE',250000);

INSERT INTO DINOSAUR
(DINO_ID, DINO_NAME, DIET_TYPE)
VALUES
(456,'TYRANNOSAURUS REX','HERBIVORE');

INSERT INTO DINOSAUR
(DINO_ID, DINO_NAME, DIET_TYPE, COST)
VALUES
(567,'TYRANNOSAURUS REX','HERBIVORE',500000);

INSERT INTO DINOSAUR
(DINO_ID, DINO_NAME, DIET_TYPE, COST)
VALUES
(789,'TYRANNOSAURUS REX','CARNIVORE',750000);

INSERT INTO LOCATION
(LOCATION_ID, LOCATION_NAME, STATE_NAME)
VALUES
('A1','BLACK HILLS','SOUTH DAKOTA');

INSERT INTO LOCATION
(LOCATION_ID, LOCATION_NAME, STATE_NAME)
VALUES
('B2','LOS ANGELES','CALIFORNIA');

INSERT INTO LOCATION
(LOCATION_ID, LOCATION_NAME, STATE_NAME)
VALUES
('C3','GRAND CANYON','ARIZONA');

INSERT INTO LOCATION
(LOCATION_ID, LOCATION_NAME, STATE_NAME)
VALUES
('D4','TAMPA','FLORIDA');

INSERT INTO LOCATION
(LOCATION_ID, LOCATION_NAME, STATE_NAME)
VALUES
('E5','ROME','NEW YORK');

INSERT INTO LOCATION
(LOCATION_ID, LOCATION_NAME, STATE_NAME)
VALUES
('F6','CALGARY','CANADA');

INSERT INTO LOCATION
(LOCATION_ID, LOCATION_NAME, STATE_NAME)
VALUES
('G7','MILWAUKEE','WISCONSIN');

INSERT INTO ARCHEOLOGIST
(ARCH_ID,FIRST_NAME,LAST_NAME)
VALUES
('ABC','ERNEST','HEMINGWAY');

INSERT INTO ARCHEOLOGIST
(ARCH_ID,FIRST_NAME,LAST_NAME)
VALUES
('DEF','AYN','RAND');

INSERT INTO ARCHEOLOGIST
(ARCH_ID,FIRST_NAME,LAST_NAME)
VALUES
('GHI','GRETA','GARBO');

INSERT INTO ARCHEOLOGIST
(ARCH_ID,FIRST_NAME,LAST_NAME)
VALUES
('JKL','FRED','ASTAIRE');

INSERT INTO ARCHEOLOGIST
(ARCH_ID,FIRST_NAME,LAST_NAME)
VALUES
('MNO','GINGER','ROGERS');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('Z12',TO_DATE('12/12/2010','MM/DD/YYYY'),123,'ABC','A1');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('A58',TO_DATE('12/15/2011','MM/DD/YYYY'),123,'ABC','C3');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('R47',TO_DATE('07/18/2012','MM/DD/YYYY'),345,'MNO','A1');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('F21',TO_DATE('06/15/2009','MM/DD/YYYY'),456,'JKL','E5');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('B65',TO_DATE('05/10/2011','MM/DD/YYYY'),456,'ABC','F6');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('O99',TO_DATE('08/20/2012','MM/DD/YYYY'),234,'MNO','G7');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('H71',TO_DATE('05/10/2012','MM/DD/YYYY'),567,'ABC','F6');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('B34',TO_DATE('07/25/2010','MM/DD/YYYY'),123,'DEF','D4');

INSERT INTO DISCOVERY
(DISC_ID, DISC_DATE, DINO_ID, ARCH_ID, LOCATION_ID)
VALUES
('K81',TO_DATE('08/01/2016','MM/DD/YYYY'),567,'MNO','B2');

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Я бы предложил что-то вроде этого:

SELECT a.first_name, a.last_name,
       COUNT(DISTINCT ds.location_id) AS locations_with_t_rex_found
  FROM archeologist a
  LEFT OUTER JOIN discovery ds
    ON ds.arch_id = a.arch_id
   AND ds.dino_id = 123
 GROUP BY a.first_name, a.last_name
 ORDER BY locations_with_t_rex_found DESC, a.first_name, a.last_name

В результате:

FIRST_NAME | LAST_NAME | LOCATIONS_WITH_T_REX_FOUND
-----------+-----------+---------------------------
Ernest     | Hemingway |                          2
Ayn        | Rand      |                          1
Fred       | Astaire   |                          0
Ginger     | Rogers    |                          0
Greta      | Garbo     |                          0

Посмотрите на это db <> fiddle , чтобы увидеть егоВ бою.(Я изменил ваши образцы данных, так как вы, кажется, называете все записи динозавров «TYRANNOSAURUS REX» в ваших вкладках, в то время как ранее вы публиковали что-то более разнообразное.)

Ключевое отличие (кромеПропуск некоторых таблиц), по сравнению с исходным запросом из этого вопроса, заключается в том, чтобы указать условие фильтрации видов динозавров в критериях соответствия левого соединения, а не в общем предложении WHERE (просто ограничить объединенную таблицу, а не весь результат).

Этот подход по сравнению с решением коррелированного подзапроса из @ Шон Петерсон также позволяет легко получать дополнительную «статистику», например, также возвращатьколичество фактических открытий (например, для покрытия нескольких открытий в одном месте), вы просто добавили бы, например, COUNT(ds.disc_id) в список выражений столбцов.

Что касается пропуска таблиц:
Вам не нужно ссылатьсятаблица LOCATION, так как вам не нужны названия местоположений, а расчет различного количества местоположений может быть основан на LOCATION_ID в DISCOVERY таблице.Вам также не понадобится таблица DINOSAUR в запросе, если только вы не хотите фильтровать T-Rex на основе имени динозавра, а не ID динозавра.Чтобы добавить таблицы обратно, вам нужно быть осторожным при присоединении.Это должно работать:

SELECT a.first_name, a.last_name,
       COUNT(DISTINCT ds.location_id) AS locations_with_t_rex_found
  FROM archeologist a
  LEFT OUTER JOIN (discovery ds
             INNER JOIN dinosaur dn ON ds.dino_id = dn.dino_id)
    ON ds.arch_id = a.arch_id
   AND dn.dino_name = 'Tyrannosaurus Rex'
 GROUP BY a.first_name, a.last_name
 ORDER BY locations_with_t_rex_found DESC, a.first_name, a.last_name
0 голосов
/ 11 февраля 2019

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

SELECT ARC.FIRST_NAME, ARC.LAST_NAME, (select count(distinct loc.LOCATION_ID) 
                                                      from DISCOVERY dis
                                                      inner join LOCATION loc on dis.location_id = loc.location_id
                                                      inner join DINOSAUR din on din.DINO_ID = dis.DINO_ID
                                                      where ARC.ARCH_ID = dis.ARCH_ID
                                                      and DIS.DINO_ID = 123) as loc_disc_TREX
FROM ARCHEOLOGIST ARC;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...