我有以下代码用于创建书店的数据库:
create database Bookorama
use Bookorama
--Book table
create table Book
(
bookID int identity(1,1),
bookName varchar(50) unique,
price smallmoney,
primary key (bookID)
);
--Customer table
create table Customer
(
custID int not null identity (1,1),
cName varchar(50),
cemid varchar(50),
primary key (custID)
);
-- Order table
create table Ordertable
(
orderID int identity(1,1),
custID int not null,
bookID int not null,
primary key (orderID),
foreign key (custid) references Customer(custid),
foreign key (bookID) references Book(bookid)
);
create table Reviews
(
reviewID int identity (1,1) not null,
custID int not null,
bookID int not null,
review varchar(50),
primary key (reviewID),
foreign key (custID) references Customer(custID),
foreign key (bookID) references Book(bookID)
)
对于我的任务,我接到了以下任务:
编写一个查询,显示所有图书的列表,对于那些有评论的人,列出评论。
我完全糊涂了,并且不知道我将如何开始接近这一点。我没有意识到我可以使用的任何JOIN组合。我对SQL很新。令我兴奋的是,我必须访问这两个表以使用书籍ID检索书名,然后创建与其相应评论的关联。同时还列出了没有评论的书籍。
答案 0 :(得分:1)
LEFT JOIN关键字返回左表(table1)中的所有记录,以及右表(table2)中的匹配记录。如果没有匹配,则结果从右侧为NULL。
例如在MSSQL上:
USE AdventureWorks2008R2;
GO
SELECT p.Name, pr.ProductReviewID
FROM Production.Product p
LEFT OUTER JOIN Production.ProductReview pr
ON p.ProductID = pr.ProductID
答案 1 :(得分:0)
出于好奇,这是家庭作业吗?
我将如何做,加入有关书籍匹配的评论:
SELECT Books.*, Reviews.review
FROM Books, Reviews
LEFT JOIN Book.bookID ON Reviews.bookID
如果您不想要没有评论的人,可以使用CTE使用WHERE子句对其进行过滤:
WITH CTE_Example
AS
(SELECT *, Reviews.review
FROM Books, Reviews
LEFT JOIN Book.bookID ON Reviews.bookID)
SELECT * FROM CTE_Example
WHERE review IS NOT NULL
SELECT *
FROM Books
LEFT JOIN Book.bookID ON Reviews.bookID
WHERE Reviews.review IS NOT NULL
根据Sean Lange,通过使用INNER JOIN跳过WHERE子句来简化查询
SELECT *
FROM Books
INNER JOIN Book.bookID ON Reviews.bookID
答案 2 :(得分:0)
只需选择bookName和评论即可。这将列出所有书籍及其评论,如果没有,则列出NULL。
SELECT bookName,
review
FROM book
LEFT JOIN reviews
ON book.bookID = reviews.bookID
答案 3 :(得分:0)
编写一个查询,显示所有图书的列表,对于那些有评论的人,列出评论。
您引用的问题陈述不明确。首先,它打算但不表达类似的东西,"显示(bookID,reviewID)行的列表......"。其次,它打算但不表达类似于" ...书中有该评论或书籍没有评论且评论ID是......"什么?你应该知道/猜测/决定完成这个......" NULL"?空字符串?谁知道,它不清楚。
或者他们可能想要"(bookName,review)行,其中一些具有该名称的书籍具有一些评论,其中文本是(列)评论或者没有评论和(列)评论是...&#34 ;. (请注意,"某些",不是""。)谁知道,它不清楚。
(这种邋iness渗透到数据库教学法和文化中。)
让我感到震惊的是,我必须访问这两个表以使用书籍ID检索书名,然后创建与其相应评论的关联。
这就是JOIN所做的。
一个表包含其值以某种方式相关/关联的行。我们可以用谓词来描述关系(发货)/关联 - 列参数化句子模板:
/* the rows where
book bookID has title bookName and costs $price
*/
select * from Book
在FROM中,每个参数表列都被重命名为以其表名/别名和点为前缀。然后INNER JOIN生成每个行的每个组合。当没有重复项时,INNER JOIN保存根据参数关联的连接/ AND关联的行。 ON和WHERE都修改FROM结果以返回通过它们的条件的连接/ AND关联的行。
...
FROM Book b JOIN Reviews r ON b.bookID = r.bookID
/* the rows where
book b.bookID has title b.bookName and costs $b.price
AND review r.reviewID is by customer r.custID of book r.bookID with text r.review
AND b.bookID = r.bookID
*/
SELECT添加&删除点前缀时删除列。当我们不想复制但可能会得到一些时,我们会使用DISTINCT。
/* the rows where
FOR SOME values for b.*, r.*,
bookID = b.bookID AND reviewID = r.reviewID
AND book b.bookID has title b.bookName and costs $b.price
AND review r.reviewID is by customer r.custID of book r.bookID with text r.review
AND b.bookID = r.bookID
*/
SELECT b.bookID, r.reviewID
FROM Book b JOIN Reviews r ON b.bookID = r.bookID
我们经常希望INNER JOIN ON中的行加上右表列的NULL不匹配的左表行。这是LEFT JOIN ON。
...
FROM Book b LEFT JOIN Reviews r ON b.bookID = r.bookID
/* the rows where
book b.bookID has title b.bookName and costs $b.price
AND review r.reviewID is by customer r.custID of book r.bookID with text r.review
AND b.bookID = r.bookID
OR book b.bookID has title b.bookName and costs $b.price
AND NOT EXISTS r.reviewID, r.custID, r.book, r.review [
review r.reviewID is by customer r.custID of book r.bookID with text r.review
AND b.bookID = r.bookID
]
AND r.reviewID IS NULL AND r.custID IS NULL AND r.book IS NULL AND r.review IS NULL
/*
所以你想要:
SELECT b.bookID, r.reviewID
FROM Book b LEFT JOIN Reviews r ON b.bookID = r.reviewID
或者也许:
SELECT DISTINCT b.bookName, r.review
FROM Book b LEFT JOIN Reviews r ON b.bookID = r.reviewID
CROSS JOIN vs INNER JOIN in SQL Server 2008
Is there any rule of thumb to construct SQL query from a human-readable description?
当存在重复或NULL时,查询很复杂,因为它们的存在在AND,OR,NOT,FOR SOME等方面变得越来越模糊地与给定情况相关(它很容易生成谓词,但他们说的很复杂。)