1

我一直在sql-ex.ru 网站上做 sql 练习,但偶然发现了一个我无法做出正确的练习。

这里是:

查找价格最高的产品(PC、笔记本电脑或打印机)的型号。

结果集:模型。

此处解释了数据库模式。我将把它的图表放在这里:

数据库架构图

我想出了这个解决方案:

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. 所以我不知道他们究竟使用哪个引擎来评估这个练习。

4

6 回答 6

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)将运行得非常快,因为数据库从表中提取最高价格。

注意:在支持表继承的数据库中(或者可以使用鉴别器列支持类似的东西),将公共列重构为单个表有很多话要说!想象一下,如果您开始销售扫描仪、显示器、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,只需要认识到这是一个更棘手但相似的查询。

于 2013-06-10T15:44:51.933 回答
1

请尝试以下方法。它是 ANSI 标准 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
)
于 2013-06-10T15:01:49.757 回答
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只使用搜索他忽略NULLs 的最高价格。这是我通过问这个问题了解到的。

于 2013-06-10T15:38:41.287 回答
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);
于 2013-06-10T15:43:00.967 回答
0

我想我发现了问题:你使用union模型和价格:如果你有两种不同的产品(代码),价格相同(最大值)和模型,你最终只给出一行(union而不是union all消除重复)。结果集是正确的,是的,但在验证中他们说你只给了一行而不是两行

于 2013-06-10T15:14:43.180 回答
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
)
于 2014-09-05T04:53:41.930 回答