Oracle中的左外联接和计数

Oracle中的左外联接和计数,oracle,Oracle,我的导师有以下问题 7) 一家博物馆要求提供所有考古学家的名字和姓氏,以及他们发现霸王龙恐龙的地点数量。请注意,一些考古学家没有发现任何恐龙,一些考古学家也没有发现任何霸王龙恐龙,但仍应列入清单 我在下面写的声明只向我展示了发现特雷克斯的考古学家。有人能帮我把问题中的所有信息都包括进去吗 SELECT ARCHEOLOGIST.FIRST_NAME, ARCHEOLOGIST.LAST_NAME,DINOSAUR.DINO_NAME, LOCATION.LOCATION_ID, COUNT

我的导师有以下问题 7) 一家博物馆要求提供所有考古学家的名字和姓氏,以及他们发现霸王龙恐龙的地点数量。请注意,一些考古学家没有发现任何恐龙,一些考古学家也没有发现任何霸王龙恐龙,但仍应列入清单

我在下面写的声明只向我展示了发现特雷克斯的考古学家。有人能帮我把问题中的所有信息都包括进去吗

 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');

我认为没有必要使用外部连接来满足问题的要求。他们要求的唯一字段是名字、姓氏和计数。。。。不需要输出恐龙的名称或位置,这意味着您可以使用下面的列表来获取所需的列表

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;

我认为没有必要使用外部连接来满足问题的要求。他们要求的唯一字段是名字、姓氏和计数。。。。不需要输出恐龙的名称或位置,这意味着您可以使用下面的列表来获取所需的列表

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;

我建议这样做:

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|u与_T_REX|u找到
-----------+-----------+---------------------------
欧内斯特|海明威| 2
艾恩兰德1
弗雷德|阿斯泰尔| 0
金吉尔|罗杰斯| 0
葛丽塔|嘉宝| 0
看看这个,看看它在起作用。(我已经调整了您的样本数据,因为您似乎在插入中将所有恐龙条目命名为“霸王龙”,而之前您发布了更为多样化的内容。)

与问题中的原始查询相比,关键区别(除了跳过一些表外)在于在左侧连接匹配条件中指定恐龙物种过滤条件,而不是在整体
WHERE
子句中(仅限制连接表,而不是整个结果)

与from相比,这种方法还允许您轻松获取其他“统计信息”,例如,要返回实际发现的计数(例如,要覆盖一个位置的多个发现),您只需将计数(ds.disc_id)添加到列表达式列表中即可

至于跳过表格:
您不需要引用
位置
表,因为您不需要位置名称,可以根据
发现
表中的
位置ID
计算不同的位置计数。您也不需要查询中的
恐龙
表,除非您希望根据恐龙名称而不是恐龙ID筛选T-Rex。 要重新添加表,您需要注意如何加入。这应该起作用:

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

我建议这样做:

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|u与_T_REX|u找到
-----------+-----------+---------------------------
欧内斯特|海明威| 2
艾恩兰德1
弗雷德|阿斯泰尔| 0
金吉尔|罗杰斯| 0
葛丽塔|嘉宝| 0
看看这个,看看它在起作用。(我已经调整了您的样本数据,因为您似乎在插入中将所有恐龙条目命名为“霸王龙”,而之前您发布了更为多样化的内容。)

与问题中的原始查询相比,关键区别(除了跳过一些表外)在于在左侧连接匹配条件中指定恐龙物种过滤条件,而不是在整体
WHERE
子句中(仅限制连接表,而不是整个结果)

与from相比,这种方法还允许您轻松获取其他“统计信息”,例如,要返回实际发现的计数(例如,要覆盖一个位置的多个发现),您只需将计数(ds.disc_id)添加到列表达式列表中即可

至于跳过表格:
您不需要引用
位置
表,因为您不需要位置名称,可以根据
发现
表中的
位置ID
计算不同的位置计数。您也不需要查询中的
恐龙
表,除非您希望根据恐龙名称而不是恐龙ID筛选T-Rex。 要重新添加表,您需要注意如何加入。这应该起作用:

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

欢迎来到堆栈溢出。请使用标签下方的
edit
按钮编辑您的问题,并包括相关表格的定义和用数据填充这些表格的语句。或者发布到数据库测试环境的链接,例如或设置并填充表的链接。没有这些信息,这里的任何人都做不了什么。谢谢。@Erica:正如Bob所问的,查看表创建和数据插入语句会很有帮助。你显然有这些,因为你已经对数据库执行了一些查询。对不起,我在这方面是全新的,只是在学习。我添加了用于创建表和插入数据的所有内容。希望这有帮助,谢谢!哈哈哈,应该说是数据库专家-学生。谢谢你:)欢迎来到Stack Overflow。请使用标签下方的
edit
按钮编辑您的问题,并包括相关表格的定义和用数据填充这些表格的语句。或者发布到数据库测试环境的链接,例如或设置并填充表的链接。没有这些信息,这里的任何人都做不了什么。谢谢。@Erica:正如Bob所问的,查看表创建和数据插入语句会很有帮助。很明显你有这些,就像你现在这样