说我有以下数据
Name Value
===============
Small 10
Medium 100
Large 1000
想象一下,这些代表了大量的盒子。我想把一些物品放在盒子里,我想要最小的盒子。我需要一个SQL查询:
很容易将其拆分为两个查询(即首先查询点1,如果没有返回行,则从表中选择最大数字)。但是,如果可能的话,我喜欢在一个查询中执行操作以消除开销(代码和上下文切换),并且看起来应该可以这样做。这可能非常明显,但太阳一整天都在照耀着我,我想不到!
因此,例如,如果使用参数5,则我希望查询返回10,如果使用参数15,则我希望返回100;如果使用大于100的任何值(包括大于1000的数字),我希望返回1000。
我使用的是Oracle 11g,所以任何特殊的Oracle优点都可以。
答案 0 :(得分:2)
SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM mytable
WHERE value > 10000
ORDER BY
value
)
UNION ALL
SELECT *
FROM (
SELECT *
FROM mytable
ORDER BY
value DESC
)
)
WHERE rownum = 1
这将有效地使用mytable(value)
和COUNT(STOPKEY)
上的索引。
请参阅我的博客中有关效果详情的文章:
答案 1 :(得分:1)
SELECT MAX(Value)
FROM Table
WHERE Value <= LEAST(@param,(SELECT MAX(Value) FROM Table))
我对Oracle并不熟悉,但我确信它具有最少的功能或类似功能。
在任何情况下,此查询的子查询都会快速使用Value
列上的正确索引。
严肃地说,你真的应该在两个查询中执行此操作(或者如果要将它们保存在同一个位置,则在一个存储过程中执行两个步骤),因为如果第一个查询有效,则不需要第二个查询。在一个查询中组合它们必然会为您提供无条件的第二(或子)查询。您必须两次查询该表,因此问题是您是否始终或仅在必要时查询两次。
答案 2 :(得分:1)
为了好玩,我假设目标大小来自一个包表,你想找到一堆包的盒子。如果第一个值为NULL,则COALESCE选择第二个值。
SELECT p.pkgid, p.pkgsize, COALESCE(MIN(b1.size), MAX(b2.size) AS boxsize FROM packages AS p LEFT JOIN boxes AS b1 ON p.pkgsize < b1.boxsize LEFT JOIN boxes AS b2 -- yes, a cartesian join GROUP BY p.pkgid, p.pkgsize
作为与其他解决方案进行比较的单一陈述,请使用
SELECT COALESCE(MIN(b1.size), MAX(b2.size) AS boxsize FROM Table AS t1, Table AS t2 WHERE targetsize < t1.Value
答案 3 :(得分:1)
WITH ranges_table AS
(SELECT LEVEL * 100 AS range_value
FROM DUAL
CONNECT BY LEVEL <= 20)
SELECT MIN (range_value)
FROM ranges_table
WHERE range_value >= 5 OR range_value = (SELECT MAX (range_value)
FROM ranges_table)
答案 4 :(得分:0)
这很有效。用参数替换“5”。
select min(basket_value) as basket_value
from baskets
where basket_value > 5
or basket_value = (select max(basket_value) from baskets)
生成测试数据的简单脚本:
create table baskets(
basket_name varchar2(20)
,basket_value number
);
insert into baskets(basket_name,basket_value) values('Small',10);
insert into baskets(basket_name,basket_value) values('Medium',100);
insert into baskets(basket_name,basket_value) values('Large',1000);
commit;
--drop table baskets; --run when finished
答案 5 :(得分:-1)
select a.newvalue from (
select MIN(value) as newvalue, 1 as order From table where value > @param
union select MAX(value) as newvalue, 2 as order from table) A
order by a.order