对于我的CIS类,我有SQL项目,我仍然是SQL的新手,并试图学习它。任何帮助将不胜感激。
查询:获取已通过销售图书" Quickbooks for Business"的员工下订单的客户的城市名称。必需:您必须使用子选择完成此查询。
这是我试过的并给我一个错误:
IProduct
我得到的错误是:#1064 - 您的SQL语法出错;查看与您的MariaDB服务器版本对应的手册,以获得在''附近使用的正确语法。在第11行
表:Table
数据库代码:
SELECT city
FROM zipcode, book, customer, orderline
where city in (SELECT city FROM zipcode WHERE
zip in (SELECT zip
FROM customer
WHERE cno IN
(SELECT cno
FROM salesorder
WHERE ono IN (SELECT ono
FROM orderline
WHERE bno IN (SELECT bno
FROM book
WHERE bname ('Quickbooks for Business') )
)
)
)
示例数据:
create table zipcode (
zip integer(5) primary key,
city varchar(30),
State varchar(20));
create table employee (
eno varchar(10) primary key,
ename varchar(30),
zip integer(5) references zipcode(zip),
hire_date date);
create table book (
bno integer(5) primary key,
bname varchar(30),
qoh integer(5) not null,
price dec(6,2) not null);
create table customer (
cno integer(5) primary key,
cname varchar(30),
street varchar(30),
zip integer(5) references zipcode(zip),
phone char(12));
create table salesOrder (
ono integer(5) primary key,
cno integer(5) references customer(cno),
eno varchar(10) references employees(Eno),
received date,
shipped date
);
create table orderLine (
ono integer(5) references salesOrder(ono),
bno integer(5) references book(bno),
quantity integer(10) not null,
primary key (ono, bno));
答案 0 :(得分:2)
您应该使用JOINS
代替Sub-Queries
:
SELECT DISTINCT Z.city
FROM zipcode Z
JOIN customer C ON C.zip = Z.zip
JOIN salesOrder S ON S.cno = C.cno
JOIN orderLine O ON O.ono = S.ono
JOIN book B ON B.bno = O.bno
WHERE B.bname = 'Quickbooks for Business'
答案 1 :(得分:0)
试试这个。虽然使用joins
可以做得更好,但这是你应该通过子查询做的。
select city from zipcode
where zip in
(select zip from customer
where cno in(
select cno from salesOrder
where ono in (
select ono from orderLine
where bno in (
SELECT bno FROM book
where bname = 'Quickbooks for Business'
)
)
)
)
答案 2 :(得分:0)
这是一个足够复杂的查询,我可以使用我称之为“测试驱动的查询设计”来解决它。或TDQD。这里有两个查询序列导致相同的合理答案 - 问题中未给出预期输出,这使得很难确定查询是否已被准确分析。
要求表述为:
通过子选择'可以解释'要求表示至少一个子查询'或者只使用子查询'。这个答案分为两部分 - 第一部分假设单个子查询就足够了,第二部分假设只能使用子查询。
我认为TDQD是一种很好的学习方法,可以学习如何通过大量的小查询构建大型查询(因为您测试了小型查询)。
这是一个相当大的第一步;如果您不熟悉编写查询,可以将其细分为较小的查询以构建员工编号的输出列表。
SELECT e.eno
FROM employee AS e
JOIN salesorder AS o ON o.eno = e.eno
JOIN orderline AS l ON o.ono = l.ono
JOIN book AS b ON l.bno = b.bno
WHERE b.bname = 'Quickbooks for Business';
输出:
P0239401
P0239402
简化:查询不需要包含employee
表;员工编号位于salesOrder
表中:
SELECT o.eno
FROM salesorder AS o
JOIN orderline AS l ON o.ono = l.ono
JOIN book AS b ON l.bno = b.bno
WHERE b.bname = 'Quickbooks for Business';
这给出了相同的结果。可以通过所有查询传播更改。请注意,答案的第二部分('所有子查询'变体)也不会从employee
表中进行选择。这种不对称应该让我早点离开,但我没有发现它。而且如果我用较小的步骤在TDQD序列中建立第一步,那么我也不会在这里犯错误。
SELECT c.cno
FROM customer AS c
JOIN salesorder AS o ON c.cno = o.cno
WHERE o.eno IN
(SELECT e.eno
FROM employee AS e
JOIN salesorder AS o ON o.eno = e.eno
JOIN orderline AS l ON o.ono = l.ono
JOIN book AS b ON l.bno = b.bno
WHERE b.bname = 'Quickbooks for Business'
);
这为您提供了强制性的子查询。
输出:
23513
23511
23513
23511
23512
23513
这是一个中间结果;没有必要删除重复项或订购此结果。
简化:
SELECT c.cno
FROM customer AS c
JOIN salesorder AS o ON c.cno = o.cno
WHERE o.eno IN
(SELECT o.eno
FROM salesorder AS o
JOIN orderline AS l ON o.ono = l.ono
JOIN book AS b ON l.bno = b.bno
WHERE b.bname = 'Quickbooks for Business'
);
SELECT DISTINCT z.city
FROM customer AS c
JOIN salesorder AS o ON c.cno = o.cno
JOIN zipcode AS z ON z.zip = c.zip
WHERE o.eno IN
(SELECT e.eno
FROM employee AS e
JOIN salesorder AS o ON o.eno = e.eno
JOIN orderline AS l ON o.ono = l.ono
JOIN book AS b ON l.bno = b.bno
WHERE b.bname = 'Quickbooks for Business'
)
ORDER BY z.city;
输出:
Bellingham
San Jose
简化:
SELECT DISTINCT z.city
FROM customer AS c
JOIN salesorder AS o ON c.cno = o.cno
JOIN zipcode AS z ON z.zip = c.zip
WHERE o.eno IN
(SELECT o.eno
FROM salesorder AS o
JOIN orderline AS l ON o.ono = l.ono
JOIN book AS b ON l.bno = b.bno
WHERE b.bname = 'Quickbooks for Business'
)
ORDER BY z.city;
作业需要子查询,但现实世界并不需要。但是,SalesOrder表必须在查询中计算两次,所以
它被别名o1
和o2
:
- TDQD第4步 - 不要使用子查询
SELECT DISTINCT z.city
FROM customer AS c
JOIN salesorder AS o1 ON c.cno = o1.cno
JOIN zipcode AS z ON c.zip = z.zip
JOIN employee AS e ON o1.eno = e.eno
JOIN salesorder AS o2 ON o2.eno = e.eno
JOIN orderline AS l ON o2.ono = l.ono
JOIN book AS b ON l.bno = b.bno
WHERE b.bname = 'Quickbooks for Business'
ORDER BY z.city;
输出:
Bellingham
San Jose
简化:
SELECT DISTINCT z.city
FROM customer AS c
JOIN salesorder AS o1 ON c.cno = o1.cno
JOIN zipcode AS z ON z.zip = c.zip
JOIN salesorder AS o2 ON o2.eno = o1.eno
JOIN orderline AS l ON o2.ono = l.ono
JOIN book AS b ON l.bno = b.bno
WHERE b.bname = 'Quickbooks for Business'
ORDER BY z.city;
如果单个子查询足够的假设是错误的,实际上只能使用子查询,那么接下来会有一个替代的TDQD序列。
SELECT b.bno
FROM book AS b
WHERE b.bname = 'Quickbooks for Business';
输出:
10605
SELECT l.ono
FROM orderline AS l
WHERE l.bno IN
(SELECT b.bno
FROM book AS b
WHERE b.bname = 'Quickbooks for Business'
);
输出:
1021
1022
SELECT DISTINCT o1.eno
FROM salesorder AS o1
WHERE o1.ono IN
(SELECT l.ono
FROM orderline AS l
WHERE l.bno IN
(SELECT b.bno
FROM book AS b
WHERE b.bname = 'Quickbooks for Business'
)
);
输出:
P0239401
P0239402
SELECT DISTINCT o2.cno
FROM salesorder AS o2
WHERE o2.eno IN
(SELECT o1.eno
FROM salesorder AS o1
WHERE o1.ono IN
(SELECT l.ono
FROM orderline AS l
WHERE l.bno IN
(SELECT b.bno
FROM book AS b
WHERE b.bname = 'Quickbooks for Business'
)
)
);
输出:
23511
23512
23513
SELECT DISTINCT c.zip
FROM customer AS c
WHERE c.cno IN
(SELECT o2.cno
FROM salesorder AS o2
WHERE o2.eno IN
(SELECT o1.eno
FROM salesorder AS o1
WHERE o1.ono IN
(SELECT l.ono
FROM orderline AS l
WHERE l.bno IN
(SELECT b.bno
FROM book AS b
WHERE b.bname = 'Quickbooks for Business'
)
)
)
);
输出:
95124
98225
SELECT DISTINCT z.city
FROM zipcode AS z
WHERE z.zip IN
(SELECT DISTINCT c.zip
FROM customer AS c
WHERE c.cno IN
(SELECT o2.cno
FROM salesorder AS o2
WHERE o2.eno IN
(SELECT o1.eno
FROM salesorder AS o1
WHERE o1.ono IN
(SELECT l.ono
FROM orderline AS l
WHERE l.bno IN
(SELECT b.bno
FROM book AS b
WHERE b.bname = 'Quickbooks for Business'
)
)
)
)
);
输出:
Bellingham
San Jose
幸运的是,为最终查询生成了相同的输出。 这使我们更加确信查询是等效的。