Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
636 views
in Technique[技术] by (71.8m points)

sql - How to make this query in Oracle

I'm implementing movies database, I have this task in my university. I have tables: movies, people, movie_people, awards. Both people and movies have field with id of award, which can be NULL. I can't get how to make SQL query which will show list of people, who played only in films which have awards. Can you help me with that?

CREATE TABLE "LAB"."MOVIE" 
   (    "MOVIE_ID" NUMBER NOT NULL ENABLE, 
    "TITLE" VARCHAR2(219 BYTE) NOT NULL ENABLE, 
    "YEARMADE" DATE, 
    "COUNTRY" VARCHAR2(40 BYTE), 
    "RUNNINGTIME" NUMBER, 
    "LANGUAGE" VARCHAR2(40 BYTE), 
    "TAG_ID" NUMBER NOT NULL ENABLE, 
    "REVIEW_ID" NUMBER, 
    "AWARD_ID" NUMBER, 
     PRIMARY KEY ("MOVIE_ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"  ENABLE, 
     FOREIGN KEY ("TAG_ID")
      REFERENCES "LAB"."TAG" ("TAG_ID") ON DELETE CASCADE ENABLE, 
     FOREIGN KEY ("REVIEW_ID")
      REFERENCES "LAB"."REVIEW" ("REVIEW_ID") ON DELETE CASCADE ENABLE, 
     CONSTRAINT "AWARD_ID" FOREIGN KEY ("AWARD_ID")
      REFERENCES "LAB"."AWARD" ("AWARD_ID") ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE TABLE "LAB"."MOVIE_PEOPLE" 
   (    "MOVIE_ID" NUMBER NOT NULL ENABLE, 
    "PEOPLE_ID" NUMBER NOT NULL ENABLE, 
    "ROLE" VARCHAR2(60 BYTE) NOT NULL ENABLE, 
     FOREIGN KEY ("MOVIE_ID")
      REFERENCES "LAB"."MOVIE" ("MOVIE_ID") ON DELETE CASCADE ENABLE, 
     FOREIGN KEY ("PEOPLE_ID")
      REFERENCES "LAB"."PEOPLE" ("PEOPLE_ID") ON DELETE CASCADE ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE TABLE "LAB"."PEOPLE" 
   (    "PEOPLE_ID" NUMBER NOT NULL ENABLE, 
    "FAMILYNAME" VARCHAR2(40 BYTE) NOT NULL ENABLE, 
    "GIVENNAME" VARCHAR2(40 BYTE) NOT NULL ENABLE, 
    "GENDER" CHAR(1 BYTE) NOT NULL ENABLE, 
    "DATEOFBIRTH" DATE, 
    "TAG_ID" NUMBER, 
    "AWARD_ID" NUMBER, 
     PRIMARY KEY ("PEOPLE_ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"  ENABLE, 
     FOREIGN KEY ("TAG_ID")
      REFERENCES "LAB"."TAG" ("TAG_ID") ON DELETE CASCADE ENABLE, 
     FOREIGN KEY ("AWARD_ID")
      REFERENCES "LAB"."AWARD" ("AWARD_ID") ON DELETE CASCADE ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE TABLE "LAB"."AWARD" 
   (    "AWARD_ID" NUMBER NOT NULL ENABLE, 
    "TITLE" VARCHAR2(40 BYTE) NOT NULL ENABLE, 
    "YEAR" DATE NOT NULL ENABLE, 
     PRIMARY KEY ("AWARD_ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"  ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One way to accomplish this would be

WITH Q1 AS (SELECT DISTINCT p.PEOPLE_ID  -- people who appeared in award-winning movies
              FROM MOVIES m
              INNER JOIN AWARDS a
                ON a.AWARD_ID = m.AWARD_ID
              INNER JOIN MOVIE_PEOPLE mp
                ON mp.MOVIE_ID = m.MOVIE_ID
              INNER JOIN PEOPLE p
                ON p.PEOPLE_ID = mp.PEOPLE_ID),
     Q2 AS (SELECT DISTINCT p.PEOPLE_ID  -- people who appeared in non-award-winning movies
              FROM MOVIES m
              INNER JOIN MOVIE_PEOPLE mp
                ON mp.MOVIE_ID = m.MOVIE_ID
              INNER JOIN PEOPLE p
                ON p.PEOPLE_ID = mp.PEOPLE_ID
              WHERE m.AWARD_ID IS NULL)
SELECT Q1.PEOPLE_ID, p.*
  FROM Q1
  INNER JOIN PEOPLE p
    ON p.PEOPLE_ID = Q1.PEOPLE_ID
  LEFT OUTER JOIN Q2
    ON Q2.PEOPLE_ID = Q1.PEOPLE_ID
  WHERE Q2.PEOPLE_ID IS NULL

Here we use the first CTE (Q1) to find all people who appeared in movies which won an award and the second CTE (Q2) to find all people who appeared in movies which did not win an award. (BTW - your design is flawed as movies can win multiple awards, but never mind...). In the main query we take all people in Q1 and outer join them to Q2, retaining only those people who appear in Q1 but not in Q2.

Best of luck.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...