2017-10-05 73 views
0

我该如何去写这个查询?我正在考虑使用count,inner join和group by。计数的书和历史

CurrentLoan是最近出版的书籍退房和历史是过去的书籍,是退房。

目标:对于每个成员(成员ID,姓氏和名字)列出成员当前签出的书籍数量以及成员过去签出的书籍数量。如果一个成员多次签出同一本书,它将被多次计数。如果成员没有书退房它应该算作0

代码:

CREATE TABLE Book 
    (bookID INT, 
    ISBN INT, 
    title varchar (30), 
    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, 'childrens'); 
INSERT INTO Book VALUES (15, 5552314569, 'Green Apple', 'Theo Brown', 1978, 'childrens'); 
INSERT INTO Book VALUES (16, 6664581631, 'Red Bean', 'Khang Nk', 2017, 'fiction'); 
INSERT INTO Book VALUES (17, 7771452369, 'XML and XQuery', 'Author Le', 2017, 'non-fiction'); 
INSERT INTO Book VALUES (18, 8881245525, 'The Dark Room', 'Jack Se', 2017, 'fiction'); 
INSERT INTO Book VALUES (19, 9991123546, 'Yellow Bird', 'Jake Red', 2014, 'reference'); 
INSERT INTO Book VALUES (20, 1122112356, 'XQuery: The XML Query Language', 'Heart Le', 2002, 'fiction'); 
INSERT INTO BOOK VALUES (21, 1212121212, 'The Giving Tree', 'Shel Silverstein', 1964, 'fiction'); 
INSERT INTO BOOK VALUES (22, 2121212121, 'Gone Fishing', 'Shel Silverstein', 1964, 'reference'); 
INSERT INTO BOOK VALUES (23, 1313131313, 'The Lazy Dog', 'Jake Red', 2016, 'childrens'); 
INSERT INTO BOOK VALUES (24, 3131313131, 'The Red Bird', 'Jake Red', 2016, 'childrens'); 
INSERT INTO BOOK VALUES (25, 1414141414, 'The Very Blue Boy', 'Ben Jen', 2006, 'fiction'); 

INSERT INTO Member VALUES (001, 'Lee', 'Nancy', 'Brownlea Drive', 1254896325, 10); 
INSERT INTO Member VALUES (002, 'Le', 'Ray', '10th Street', 1234561256, 2); 
INSERT INTO Member VALUES (003, 'Kan', 'Charlie', '5th Street', 1234567236, 8); 
INSERT INTO Member VALUES (004, 'Brown', 'Joe', 'Elm Street', 1234567845, 9); 
INSERT INTO Member VALUES (005, 'Smith', 'John', '33 East', 1234567890, 3); 
INSERT INTO Member VALUES (006, 'Khang', 'Nkaujyi', '358 Spencer', 2145345625, 5); 
INSERT INTO Member VALUES (007, 'Jones', 'David', '4th Street', 14812365789, 10); 
INSERT INTO Member values (008, 'Lee', 'Tou', 'Lee Street', 2145632562, 1); 
INSERT INTO Member values (009, 'Jones', 'John', '1st Street', 0124789541, 7); 

INSERT INTO CurrentLoan VALUES (006, 17, '14-FEB-17', '12-MAR-17'); 
INSERT INTO CurrentLoan VALUES (004, 17, '12-OCT-17', '09-NOV-17'); 
INSERT INTO CurrentLoan VALUES (004, 20, '12-OCT-17', '09-NOV-17'); 
INSERT INTO CurrentLoan VALUES (005, 18, '13-APR-17', '12-MAY-17'); 
INSERT INTO CurrentLoan VALUES (007, 25, '02-OCT-17', '25-DEC-17'); 
INSERT INTO CurrentLoan VALUES (008, 15, '03-MAY-17', '08-AUG-17'); 
INSERT INTO CurrentLoan VALUES (008, 12, '03-MAY-17', '08-AUG-17'); 
INSERT INTO CurrentLoan VALUES (009, 12, '02-OCT-17', '23-NOV-17'); 
INSERT INTO CurrentLoan VALUES (009, 14, '23-JUN-17', '24-OCT-17'); 

INSERT INTO History VALUES (008, 12, '03-JAN-16', '25-MAY-16'); 
INSERT INTO History VALUES (008, 15, '03-JAN-16', '25-MAY-16'); 
INSERT INTO History VALUES (009, 20, '12-FEB-16', '05-MAY-16'); 
INSERT INTO History VALUES (009, 15, '12-JUN-16', '05-AUG-16'); 
INSERT INTO History VALUES (006, 20, '14-MAY-16', '04-DEC-16'); 
INSERT INTO History VALUES (007, 12, '02-OCT-16', '25-DEC-16'); 
COMMIT; 

这是我到目前为止,查询:

​​

这就是我想要的输出是:

memberID lastname firstname numberofbooks 
1   Lee   Nancy  0 
2   Le   Ray   0 
3   Kan   Charlie  0 
4   Brown  Joe   2 
5   Smith  John   1 
6   Khang  Nkaujyi  2 
7   Jones  David  2 
8   Lee   Tou   4 
9   Jones  John   4 

回答

1

要在零的数列到达,你需要在数据的NULL,因为COUNT()不INCREM ent为NULL,但在任何非NULL值时递增。为了得到NULL值到结果使用外连接(在这里,他们是左外连接)。

SELECT Member.memberID, lastname, firstname, COUNT (CurrentLoan.bookID) as Current_ 
FROM Member 
LEFT OUTER JOIN CurrentLoan ON Member.memberID = CurrentLoan.memberID 
/* LEFT OUTER JOIN Book ON CurrentLoan.bookID = Book.bookID */ 
GROUP BY Member.memberID, lastname, firstname 
ORDER BY Member.memberID, lastname, firstname 

nb:除非打算使用该表中的某个列,否则不需要第二个左连接。

看到这个SQL Fiddle

Results

| MEMBERID | LASTNAME | FIRSTNAME | CURRENT_ | 
|----------|----------|-----------|----------| 
|  1 |  Lee |  Nancy |  0 | 
|  2 |  Le |  Ray |  0 | 
|  3 |  Kan | Charlie |  0 | 
|  4 | Brown |  Joe |  2 | 
|  5 | Smith |  John |  1 | 
|  6 | Khang | Nkaujyi |  1 | 
|  7 | Jones |  David |  1 | 
|  8 |  Lee |  Tou |  2 | 
|  9 | Jones |  John |  2 | 

与历史

SELECT Member.memberID, lastname, firstname, COUNT (Loans.bookID) as Count_All 
FROM Member 
LEFT OUTER JOIN (
     select memberID, bookID from CurrentLoan 
     union all 
     select memberID, bookID from History 
    ) loans ON Member.memberID = Loans.memberID 
/* LEFT OUTER JOIN Book ON CurrentLoan.bookID = Book.bookID */ 
GROUP BY Member.memberID, lastname, firstname 
ORDER BY Member.memberID, lastname, firstname 
+0

只是到目前,其中的历史(过去)的作品?它应该能够获得当前和历史成员的书籍总数。 – tubvajlis

+0

善良,为什么不尝试自己的东西,更好的学习方式,但在一会儿,我会添加缺少的加入,并计数 –

+0

我一直在做这个问题近4个小时,无法得到它。 – tubvajlis

1

的乐趣比较:看http://sqlfiddle.com/#!4/aa53f/10

SELECT Member.memberID, lastname, firstname, COUNT (Loans.bookID) as Count_All 
FROM Member 
LEFT OUTER JOIN (
     select memberID, bookID from CurrentLoan 
     union all 
     select memberID, bookID from History 
    ) loans ON Member.memberID = Loans.memberID 
GROUP BY Member.memberID, lastname, firstname 
ORDER BY Member.memberID, lastname, firstname 
; 

----------------------------------------------------------------------------------- 
| Id | Operation     | Name  | Rows | Bytes | Cost | Time  | 
----------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT   |    | 15 | 945 | 9 | 00:00:01 | 
| 1 | SORT GROUP BY   |    | 15 | 945 | 9 | 00:00:01 | 
| * 2 | HASH JOIN OUTER   |    | 15 | 945 | 8 | 00:00:01 | 
| 3 |  TABLE ACCESS FULL  | MEMBER  | 9 | 333 | 3 | 00:00:01 | 
| 4 |  VIEW     |    | 15 | 390 | 4 | 00:00:01 | 
| 5 |  UNION-ALL    |    |  |  |  |   | 
| 6 |  INDEX FAST FULL SCAN | SYS_C007213 | 9 | 234 | 2 | 00:00:01 | 
| 7 |  INDEX FAST FULL SCAN | SYS_C007216 | 6 | 156 | 2 | 00:00:01 | 
----------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
------------------------------------------ 
* 2 - access("MEMBER"."MEMBERID"="LOANS"."MEMBERID"(+)) 

现在就试试THI方式:

SELECT Member.memberID, lastname, firstname, NVL(Loans.Count_All,0) Count_All 
FROM Member 
LEFT OUTER JOIN (
     select memberID, count(bookID) as Count_All 
     from (
      select memberID, bookID from CurrentLoan 
      union all 
      select memberID, bookID from History 
      ) l 
     GROUP BY memberID 
    ) loans ON Member.memberID = Loans.memberID 
ORDER BY Member.memberID, lastname, firstname 
; 

------------------------------------------------------------------------------------- 
| Id | Operation     | Name  | Rows | Bytes | Cost | Time  | 
------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |    | 15 | 945 | 10 | 00:00:01 | 
| 1 | SORT ORDER BY    |    | 15 | 945 | 10 | 00:00:01 | 
| * 2 | HASH JOIN OUTER   |    | 15 | 945 | 9 | 00:00:01 | 
| 3 |  TABLE ACCESS FULL  | MEMBER  | 9 | 333 | 3 | 00:00:01 | 
| 4 |  VIEW      |    | 15 | 390 | 5 | 00:00:01 | 
| 5 |  HASH GROUP BY   |    | 15 | 390 | 5 | 00:00:01 | 
| 6 |  VIEW     |    | 15 | 390 | 4 | 00:00:01 | 
| 7 |  UNION-ALL    |    |  |  |  |   | 
| 8 |   INDEX FAST FULL SCAN | SYS_C007213 | 9 | 234 | 2 | 00:00:01 | 
| 9 |   INDEX FAST FULL SCAN | SYS_C007216 | 6 | 156 | 2 | 00:00:01 | 
------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
------------------------------------------ 
* 2 - access("MEMBER"."MEMBERID"="LOANS"."MEMBERID"(+)) 

所以,在这个测试中第二个方法不是更好?