2017-09-23 92 views
4

這是說我沒有選擇行。它說我沒有選擇行?

這就是問題: 找到過去或現在從未借過任何書籍的成員的會員ID,姓氏和名字。

這是模式,主鍵是粗體。

書(BOOKID,ISBN,書名,作者,出版年,類別)

會員(MEMBERID,姓氏,名字,地址,電話號碼,限制)

CurrentLoan( MEMBERIDBOOKID,貸款日期,到期日期)

歷史(MEMBERIDbookID,loan-date,return-date)

會員可以從圖書館借書。他們可以借閱的書籍數量受到會員關係「限制」字段的限制(對於不同的會員可能會有所不同)。一本書的類別包括小說,非小說,兒童和參考。 CurrentLoan表格表示當前檢出的書籍信息。當書籍返回到圖書館時,記錄將從CurrentLoad關係中刪除,並將插入到與返回日期相關的歷史記錄關係中。圖書館可能有同一本書的多個副本,在這種情況下,每個副本都有自己的bookID,但所有副本都共享相同的ISBN。

這是我的代碼:

CREATE TABLE Book 
    (bookID INT, 
    ISBN INT, 
    title varchar (25), 
    author varchar (20), 
    publish_year INT, 
    category varchar(20), 
    PRIMARY KEY (bookID)); 

CREATE TABLE Member 
    (memberID INT, 
    lastname varchar (20), 
    firstname varchar (20), 
    address varchar(20), 
    phone_number INT, 
    limit_ INT, 
    PRIMARY KEY (memberID)); 

CREATE TABLE CurrentLoan 
    (memberID INT , 
    bookID INT, 
    loan_date DATE, 
    due_date DATE, 
    PRIMARY KEY (memberID, bookID), 
    FOREIGN KEY (memberID) REFERENCES Member(memberID), 
    FOREIGN KEY (bookID) REFERENCES Book(bookID)); 


CREATE TABLE History 
    (memberID INT, 
    bookID INT, 
    loan_date DATE, 
    return_date DATE, 
    PRIMARY KEY (memberID, bookID, loan_date), 
    FOREIGN KEY (memberID) REFERENCES Member(memberID), 
    FOREIGN KEY (bookID) REFERENCES Book(bookID)); 

INSERT INTO Book VALUES (10, 1113312336, 'The Dog', 'Jack Crow', 1990, 'fiction'); 
INSERT INTO Book VALUES (12, 2221254896, 'Worms', 'Jim Kan', 2013, 'childrens'); 
INSERT INTO Book VALUES (13, 3332546987, 'Crow', 'Jan Flo', 2000, 'fiction'); 
INSERT INTO Book VALUES (14, 4443456215, 'Big Dog', 'Lan Big', 1993, 'children'); 
INSERT INTO Book VALUES (15, 5552314569, 'Green Apple', 'Theo Brown', 1978, 'children'); 
INSERT INTO Book VALUES (16, 6664581631, 'Red Bean', 'Khang Nk', 2017, 'fiction'); 
INSERT INTO Book VALUES (17, 7771452369, 'XML and XQuery Knowledge', 'Author Le', 2017, 'non-fiction'); 
INSERT INTO Book VALUES (18, 8881245525, 'The Dark Room', 'Jack Se', 2017, 'fiction'); 
INSERT INTO Book VALUES (19, 9991123546, 'Lonely Mens', 'Geen Brown', 2014, 'refrence'); 
INSERT INTO Book VALUES (20, 1122112356, 'XML or XQuery', 'Heart Le', 2002, 'fiction'); 

INSERT INTO Member VALUES (001, 'Lee', 'Nancy', 'Brownlea Drive', 1254896325, 2); 
INSERT INTO Member VALUES (002, 'Le', 'Ray', '10th Street', 1234561256, 2); 
INSERT INTO Member VALUES (003, 'Kan', 'Charlie', '5th Street', 1234567236, 2); 
INSERT INTO Member VALUES (004, 'Brown', 'Joe', 'Elm Street', 1234567845, 2); 
INSERT INTO Member VALUES (005, 'Smith', 'John', '33 East', 1234567890, 2); 

INSERT INTO CurrentLoan VALUES (005, 10, '13-SEP-17', '14-NOV-17'); 
INSERT INTO CurrentLoan VALUES (005, 19, '13-JAN-17', '15-NOV-17'); 
INSERT INTO CurrentLoan VALUES (003, 16, '14-FEB-17', '12-MAR-17'); 
INSERT INTO CurrentLoan VALUES (004, 15, '12-OCT-17', '09-NOV-17'); 
INSERT INTO CurrentLoan VALUES (005, 18, '13-APR-17', '12-MAY-17'); 

INSERT INTO History VALUES (001, 10, '14-Jan-17', '04-OCT-17'); 
INSERT INTO History VALUES (002, 19, '12-Jan-17', '04-NOV-17'); 
INSERT INTO History VALUES (003, 13, '14-APR-17', '08-OCT-17'); 
INSERT INTO History VALUES (005, 20, '14-MAY-17', '04-DEC-17'); 

我的查詢是:

SELECT Member.memberID, lastname, firstname 
    FROM Member MINUS(
        SELECT Member.memberID, lastname, firstname 
        FROM Member, CurrentLoan 
        WHERE Member.memberID = CurrentLoan.memberID 
        UNION 
        SELECT Member.memberID, lastname, firstname 
        FROM Member, History 
        WHERE Member.memberID = History.memberID); 
+0

您使用的是MySQL還是Oracle?爲什麼在'FROM'子句中使用逗號?這是古老的語法。使用正確,明確的'JOIN'語法。 –

+1

您正在扣除'MINUS'語句的謂詞中的所有五個'成員'記錄。完全預期空的結果集。 –

+0

@GordonLinoff對不起,我使用Oracle – tubvajlis

回答

1

有幾個方法可以做到這一點:

您可以使用反連接,如:

SELECT m.MEMBERID, 
     m.LASTNAME, 
     m.FIRSTNAME 
    FROM MEMBERS m 
    WHERE m.MEMBERID NOT IN (SELECT DISTINCT MEMBERID 
          FROM CURRENTLOAN 
          UNION ALL 
          SELECT DISTINCT MEMBERID 
          FROM HISTORY); 

另一種方式(和我的首選方法)做你想要的是:

SELECT DISTINCT m.MEMBERID, 
       m.LASTNAME, 
       m.FIRSTNAME 
    FROM MEMBERS m 
    LEFT OUTER JOIN (SELECT DISTINCT MEMBERID 
        FROM (SELECT MEMBERID 
          FROM CURRENTLOAN 
          UNION ALL 
          SELECT MEMBERID 
          FROM HISTORY)) u 
    ON u.MEMBERID = m.MEMBERID 
    WHERE u.MEMBERID IS NULL; 

然而,鑑於你已經證明這個查詢,以及您的原始查詢的數據,應該返回零行。 SQLFiddle here

請注意,如果您註釋掉當前貸款成員004,那麼「喬布朗」返回SQLFiddle here

好運。

+0

這將有助於理解*爲什麼*您更喜歡通過反連接進行外連接。人們會期望(有些人會聲稱他們可以證明)Oracle優化了反連接,因此它們比更一般的左連接更快。 (從邏輯上講,很明顯 - 平均來說,反連接需要檢查「右側表」中只有一半行將被拒絕的行。標準連接將始終檢查右側的所有行,旁邊的桌子。) – mathguy

+0

@mathguy:有趣。我會很感興趣,如果你花時間回答[這個問題](https://stackoverflow.com/questions/46383003/is-an-anti-join-more-efficient-than-a-left-outer -加入)。謝謝。 –

+0

至於「爲什麼我更喜歡用外部連接加過濾器來反連接」 - 我想這可能是我與Rdb定期合作的日子裏的遺留問題,在我11歲的時候,反連接一般很慢。舊習難改。 :-)我也會編輯並添加反連接方法。 –

相關問題