查找表中的最大值大于某个值

时间:2009-04-20 16:34:18

标签: sql oracle

说我有以下数据

Name      Value
===============
Small        10
Medium      100
Large      1000

想象一下,这些代表了大量的盒子。我想把一些物品放在盒子里,我想要最小的盒子。我需要一个SQL查询:

  1. 返回最小行大于查询参数
  2. 的行
  3. 如果没有这样的行,则返回最大的行。
  4. 很容易将其拆分为两个查询(即首先查询点1,如果没有返回行,则从表中选择最大数字)。但是,如果可能的话,我喜欢在一个查询中执行操作以消除开销(代码和上下文切换),并且看起来应该可以这样做。这可能非常明显,但太阳一整天都在照耀着我,我想不到!

    因此,例如,如果使用参数5,则我希望查询返回10,如果使用参数15,则我希望返回100;如果使用大于100的任何值(包括大于1000的数字),我希望返回1000。

    我使用的是Oracle 11g,所以任何特殊的Oracle优点都可以。

6 个答案:

答案 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