SQL 查询:Select 子选择的最大值
SQL query: Select max value of subselect
我有一个已经有效的 sql 语句,但我认为一定有比我的更好的解决方案。
我正在尝试 获取 文章 最高价格 其中有 从未售出.
有了这个select我得到了所有还没有售出的物品(数量+价格):
select anr, price
from article a
where not exists(
select 1 from OrderItems o
where o.artnr = a.anr
)
货号+价格结果好像
| Anr | Price |
| 1 | 300.0 |
| 4 | 340.0 |
| 5 | 340.0 |
| 3 | 200.0 |
我临时获取价格最高的文章的解决方案是:
select anr, price
from article
where anr in(
select anr
from article a
where not exists(
select 1 from OrderItems o
where o.artnr = a.anr
)
)
and price = (
select max(price)
from article a
where not exists(
select 1 from OrderItems o
where o.artnr = a.anr
)
)
正确的解法是:
| Anr | Price |
| 4 | 340.0 |
| 5 | 340.0 |
有没有办法避免相同的 subselect 两次?
此处用于测试的是带有我的插入值的缩短的创建 Table 脚本:
CREATE TABLE Article
(
Anr Int Primary Key,
Price Numeric(9,2) Not Null
);
CREATE TABLE Orders
(
OrderNr Int Primary Key
)
CREATE TABLE OrderItems
(
OrderNr Int References Orders On Delete Cascade,
ItemNr Int,
Artnr Int References Article Not Null,
Amount Int Not Null Check(Amount >= 0),
Primary Key(OrderNr, ItemNr)
)
-- articles without an order
Insert into Article (Anr, Price) values(1,300.0);
Insert into Article (Anr, Price) values(4,340.0);
Insert into Article (Anr, Price) values(5,340.0);
Insert into Article (Anr, Price) values(3,200.0);
-- articles for order with orderNr '1'
Insert into Article (Anr, Price) values(2,340.0);
Insert into Article (Anr, Price) values(6,620.0);
-- insert test order that contains the two articles
Insert into Orders (OrderNr) values (1);
Insert into OrderItems(OrderNr, ItemNr, Artnr, Amount) values(1,1,2,4);
Insert into OrderItems(OrderNr, ItemNr, Artnr, Amount) values(1,2,6,2);
我也看了题目
但我认为就我而言,必须有更短的方法来完成 select.
这是一个解决方案,它避免了您拥有的一个相关子查询,而是将其替换为 LEFT JOIN
:
SELECT a.*
FROM article a LEFT JOIN OrderItems o ON a.anr = o.artnr
WHERE o.artnr IS NULL AND
a.price = (SELECT MAX(a.price)
FROM article a LEFT JOIN OrderItems o ON a.anr = o.artnr
WHERE o.artnr IS NULL)
此解决方案应符合 ANSI-92,这意味着它应该与 MySQL、Oracle、SQL 服务器以及您可能遇到的任何其他类型的快餐兼容。
您可以将原始查询与 window 函数结合使用来获得您想要的结果:
select anr, price
from (
select anr, price, max(price) over () as max_price
from article a
where not exists (select 1
from OrderItems o
where o.artnr = a.anr)
) t
where price = max_price;
这 可能 更快,因为只需要对 article
table 进行一次扫描。
或者,您可以使用左连接解决方案来查找从未被订购的文章,但如果 Oracle 会为此使用不同的执行计划,我会感到惊讶:
select anr, price
from (
select anr, price, max(price) over () as max_price
from article a
left join OrderItems o ON o.artnr = a.anr
where o.artnr is null
) t
where price = max_price;
SQLFiddle 示例:http://sqlfiddle.com/#!15/1eb69/1
SELECT a.*
FROM article a LEFT JOIN OrderItems o ON a.anr = o.artnr
WHERE o.artnr IS NULL
AND a.price = (SELECT TOP 1 a.price
FROM article a LEFT JOIN OrderItems o ON a.anr = o.artnr
WHERE o.artnr IS NULL
Order By a.price Desc
)
试试这个....
我有一个已经有效的 sql 语句,但我认为一定有比我的更好的解决方案。
我正在尝试 获取 文章 最高价格 其中有 从未售出.
有了这个select我得到了所有还没有售出的物品(数量+价格):
select anr, price
from article a
where not exists(
select 1 from OrderItems o
where o.artnr = a.anr
)
货号+价格结果好像
| Anr | Price |
| 1 | 300.0 |
| 4 | 340.0 |
| 5 | 340.0 |
| 3 | 200.0 |
我临时获取价格最高的文章的解决方案是:
select anr, price
from article
where anr in(
select anr
from article a
where not exists(
select 1 from OrderItems o
where o.artnr = a.anr
)
)
and price = (
select max(price)
from article a
where not exists(
select 1 from OrderItems o
where o.artnr = a.anr
)
)
正确的解法是:
| Anr | Price |
| 4 | 340.0 |
| 5 | 340.0 |
有没有办法避免相同的 subselect 两次?
此处用于测试的是带有我的插入值的缩短的创建 Table 脚本:
CREATE TABLE Article
(
Anr Int Primary Key,
Price Numeric(9,2) Not Null
);
CREATE TABLE Orders
(
OrderNr Int Primary Key
)
CREATE TABLE OrderItems
(
OrderNr Int References Orders On Delete Cascade,
ItemNr Int,
Artnr Int References Article Not Null,
Amount Int Not Null Check(Amount >= 0),
Primary Key(OrderNr, ItemNr)
)
-- articles without an order
Insert into Article (Anr, Price) values(1,300.0);
Insert into Article (Anr, Price) values(4,340.0);
Insert into Article (Anr, Price) values(5,340.0);
Insert into Article (Anr, Price) values(3,200.0);
-- articles for order with orderNr '1'
Insert into Article (Anr, Price) values(2,340.0);
Insert into Article (Anr, Price) values(6,620.0);
-- insert test order that contains the two articles
Insert into Orders (OrderNr) values (1);
Insert into OrderItems(OrderNr, ItemNr, Artnr, Amount) values(1,1,2,4);
Insert into OrderItems(OrderNr, ItemNr, Artnr, Amount) values(1,2,6,2);
我也看了题目
这是一个解决方案,它避免了您拥有的一个相关子查询,而是将其替换为 LEFT JOIN
:
SELECT a.*
FROM article a LEFT JOIN OrderItems o ON a.anr = o.artnr
WHERE o.artnr IS NULL AND
a.price = (SELECT MAX(a.price)
FROM article a LEFT JOIN OrderItems o ON a.anr = o.artnr
WHERE o.artnr IS NULL)
此解决方案应符合 ANSI-92,这意味着它应该与 MySQL、Oracle、SQL 服务器以及您可能遇到的任何其他类型的快餐兼容。
您可以将原始查询与 window 函数结合使用来获得您想要的结果:
select anr, price
from (
select anr, price, max(price) over () as max_price
from article a
where not exists (select 1
from OrderItems o
where o.artnr = a.anr)
) t
where price = max_price;
这 可能 更快,因为只需要对 article
table 进行一次扫描。
或者,您可以使用左连接解决方案来查找从未被订购的文章,但如果 Oracle 会为此使用不同的执行计划,我会感到惊讶:
select anr, price
from (
select anr, price, max(price) over () as max_price
from article a
left join OrderItems o ON o.artnr = a.anr
where o.artnr is null
) t
where price = max_price;
SQLFiddle 示例:http://sqlfiddle.com/#!15/1eb69/1
SELECT a.*
FROM article a LEFT JOIN OrderItems o ON a.anr = o.artnr
WHERE o.artnr IS NULL
AND a.price = (SELECT TOP 1 a.price
FROM article a LEFT JOIN OrderItems o ON a.anr = o.artnr
WHERE o.artnr IS NULL
Order By a.price Desc
)
试试这个....