我一直在从sql-ex.ru site进行sql练习,偶然发现了一个我无法纠正的练习。
这是:
使用以下方法查找产品(PC,笔记本电脑或打印机)的型号 最高的价格。
结果集:模型。
解释数据库模式here。我将把它的图表放在这里:
我提出了这个解决方案:
with model_price(model,price) as (
select model,price
from PC
union
select model,price
from Laptop
union
select model,price
from Printer
)
select model
from model_price
where price >= all(select price from model_price)
系统输出以下结果:
Your query produced correct result set on main database, but it failed test on second, checking database.
* Wrong number of records (less by 2)
系统为main database
提供答案。但是我不知道检查数据库是什么,并且无法通过单独执行子查询并查找我犯错的位置来确定错误。
所以我在这里问,希望你能注意到我做错了什么。这个任务是2级(非常简单),所以它应该是一件微不足道的事情,我不知道。
关于sql引擎:Now we use Microsoft SQL Server 2012 on the rating stages, and MySQL 5.5.11, PostgreSQL 9.0, and Oracle Database 11g on the learn stage in addition.
所以我不知道他们用什么引擎来评估这个练习。
答案 0 :(得分:1)
请试试以下内容。它是ANSI-Standard SQL,因此您不必担心使用哪种RDBMS。
SELECT
model
FROM
(
SELECT
model, price
FROM
pc
UNION ALL
SELECT
model, price
FROM
printer
UNION ALL
SELECT
model, price
FROM
laptop
) sq
WHERE price = (SELECT MAX(price) FROM (
SELECT
model, price
FROM
pc
UNION ALL
SELECT
model, price
FROM
printer
UNION ALL
SELECT
model, price
FROM
laptop
) sq2
)
答案 1 :(得分:1)
解决方案是使用带有max
函数的子查询,而不是与all
进行比较:
with model_price(model,price) as (
select model,price
from PC
union
select model,price
from Laptop
union
select model,price
from Printer
)
select model
from model_price
where price = (select max(price) from model_price)
不需要distinct
关键字,因为union
会返回唯一的行。
感谢 tombom 帮助我找到了这个。
使用all
的解决方案不起作用,因为price
列可能包含NULL
个值,并且与NULL
相比产生false
,这使得all
false
的整个结果,而使用max
只搜索忽略NULL
s的最高价格。我通过询问this question了解到了这一点。
答案 2 :(得分:1)
SELECT model, price FROM (
(SELECT model, price FROM pc ORDER BY price DESC LIMIT 1)
/* your database may use a TOP 1 syntax for the LIMIT queries */
UNION ALL
(SELECT model, price FROM laptop ORDER BY price DESC LIMIT 1)
UNION ALL
(SELECT model, price FROM printer ORDER BY price DESC LIMIT 1)
) AS subquery_name_required
ORDER BY price DESC LIMIT 1;
如果价格字段已编入索引(对于这样的查询应该是这样),ORDER / LIMIT(或等效的TOP)将在DB从表中获取最高价格时运行得非常快。
注意:在支持表继承的数据库中(或者可以使用鉴别器列来支持类似于它的东西),将公共列重构为单个表有很多可说的内容!想象一下,如果你开始销售scaners,显示器,SSD等 - 这真是一场噩梦!
[编辑显示关系]
SELECT model, price FROM (
SELECT model, price FROM
(SELECT model, price, rank() OVER (ORDER BY price DESC) AS r FROM pc) AS s1
WHERE r=1
/* your database may not yet support windowing queries;
in that case you probably have to compare to MAX,
which may mean an extra pass through every table. */
UNION ALL
SELECT model, price FROM
(SELECT model, price, rank() OVER (ORDER BY price DESC) AS r FROM laptop) AS s2
WHERE r=1
UNION ALL
SELECT model, price FROM
(SELECT model, price, rank() OVER (ORDER BY price DESC) AS r FROM printer) AS s3
WHERE r=1
) AS subquery_name_required
ORDER BY price DESC LIMIT 1;
我没有足够的经验来处理这种窗口,以确定是否会根据需要扫描price
上的索引。希望如此。从概念上讲,这不应该比LIMIT 1
更难,只需要认识到这是一个棘手但相似的查询。
答案 3 :(得分:0)
我认为我发现了这个问题:您使用union
模型和价格:如果您有两个不同的产品(代码)具有相同的价格(最大值)和模型,您最终只给出一行({{ 1}}代替union
消除重复项。
结果集是正确的,是的,但在验证中他们说你只给了一行而不是两行
答案 4 :(得分:0)
WITH tab1 as
(
/* laptop */
(
SELECT 1 model, 2000 price FROM DUAL UNION ALL
SELECT 2 model, 2250 price FROM DUAL UNION ALL
SELECT 3 model, 2500 price FROM DUAL UNION ALL
SELECT 4 model, 2550 price FROM DUAL -- <---- the highest value
)
UNION ALL
/* printer */
(
SELECT 5 model, 500 price FROM DUAL UNION ALL
SELECT 6 model, 750 price FROM DUAL UNION ALL
SELECT 7 model, 1000 price FROM DUAL UNION ALL
SELECT 8 model, 1250 price FROM DUAL
)
UNION ALL
/* pc */
(
SELECT 9 model, 1000 price FROM DUAL UNION ALL
SELECT 10 model, 1250 price FROM DUAL UNION ALL
SELECT 11 model, 1500 price FROM DUAL UNION ALL
SELECT 12 model, 1750 price FROM DUAL
)
)
SELECT model
FROM tab1
WHERE price = (SELECT MAX(price) FROM tab1);
答案 5 :(得分:0)
select model
from (Select model, price from pc
where price = (select max(price) from pc)
union
Select model, price from laptop
where price = (select max(price) from laptop)
union
Select model, price from printer
where price = (select max(price) from printer)
) as A
where price = (
select max(price) from (
Select model, price from pc
where price = (select max(price) from pc)
union
Select model, price from laptop
where price = (select max(price) from laptop)
union
Select model, price from printer
where price = (select max(price) from printer)
) as B
)