Oracle - 返回一组行中的最短字符串值

时间:2010-04-20 16:14:49

标签: sql oracle plsql

我正在尝试编写一个返回列中最短字符串值的查询。例如:如果ColumnA具有值ABCDE,ZXDR,ERC,则查询应返回“ERC”。我写了以下查询,但我想知道是否有更好的方法来做到这一点?

查询应返回单个值。

select distinct ColumnA from
(
  select ColumnA, rank() over (order by length(ColumnA), ColumnA) len_rank 
    from TableA where ColumnB = 'XXX'
)
where len_rank <= 1

7 个答案:

答案 0 :(得分:9)

怎么样:

select ColumnA
from
(
  select ColumnA
  from tablea
  order by length(ColumnA) ASC
)
where rownum = 1

答案 1 :(得分:2)

这将帮助您获得列中具有最小长度的所有字符串。

select ColumnA 
from TableA 
where length(ColumnA) = (select min(length(ColumnA)) from TableA)

希望这有帮助。

答案 2 :(得分:1)

最简单的方法,使用单个表访问且没有子查询:

SQL> create table mytable (txt)
  2  as
  3  select 'ABCDE' from dual union all
  4  select 'ZXDR' from dual union all
  5  select 'ERC' from dual
  6  /

Table created.

SQL> set autotrace on explain
SQL> select min(txt) keep (dense_rank first order by length(txt)) txt
  2    from mytable
  3  /

TXT
-----
ERC

1 row selected.


Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (AGGREGATE)
   2    1     TABLE ACCESS (FULL) OF 'MYTABLE'

编辑:我调整了示例以更符合您的示例查询:

SQL> create table tablea (columna,columnb)
  2  as
  3  select 'ABCDE', 'XXX' from dual union all
  4  select 'ZXDR', 'XXX' from dual union all
  5  select 'ERC', 'XXX' from dual
  6  /

Table created.

SQL> set autotrace on explain
SQL> select min(columna) keep (dense_rank first order by length(columna)) columna
  2    from tablea
  3   where columnb = 'XXX'
  4  /

COLUM
-----
ERC

1 row selected.


Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (AGGREGATE)
   2    1     TABLE ACCESS (FULL) OF 'TABLEA'

此致 罗布。

答案 3 :(得分:0)

这个问题分为两部分。确定最短字符串的另一种方法是老式的子查询:

select distinct ColumnA 
from tablea 
where length(ColumnA) = ( select min(length(ColumnA)) 
                          from TableA 
                          where ColumnB = 'XXX'
                        )
/

哪个更好?这取决于索引,数据量等,但我猜你的版本可能会表现更好。除非您在外部查询中重复where ColumnB = 'XXX',否则它可能会给出略有不同的结果。

与您的解决方案一样,此查询将为ColumnA的每个值返回一行,其中三个字符长。如果要返回单行,可以通过使用rownum限制它来执行此操作。你想要应用一些标准来确定哪一个是你需要将它嵌入到另一个外部查询中的第一行(使用我的查询但你的变体也可以工作)...

select * from (
    select ColumnA 
    from tablea 
    where length(ColumnA) = ( select min(length(ColumnA)) 
                              from TableA 
                              where ColumnB = 'XXX'
                            )
    order by ColumnA
    ) 
where rownum = 1
/

答案 4 :(得分:0)

稍微扩展APC的答案,我认为这会稍微好一些:

SELECT DISTINCT columna
  FROM tablea t1
 WHERE EXISTS ( SELECT 1 FROM tablea t2
                 WHERE LENGTH(t2.columna) = MIN(LENGTH(t1.columna)) )
   AND rownum = 1
IIRC,APC的子选择将在tablea中的每一行运行一次。我相信,这不是。

请注意,如果columna中有多个行具有相同的长度字符串,则可能无法从此查询中多次运行获得一致的结果。

答案 5 :(得分:0)

我知道这有很长的答案而且很老。 但我想我知道另一个好方法。

因为所有答案都使用子查询,所以它不适合我的情况。 所以我找到了一种未使用子查询的方法。

说我有以下数据。

select  *
from    (select 'x' f  from dual union all select 'aaaaa' from dual) a

- 输出

x
aaaaa

如果我选择min of value,则返回'aaaaa',因为'a'小于ascii顺序中的'x'。

select  min(a.f)
from    (select 'x' f  from dual union all select 'aaaaa' from dual) a

- 输出

aaaaa

但是,如果我选择min的长度,它将返回1(这是'x'值),因为1按数字顺序小于5。

select  min(length(a.f))
from    (select 'x' f  from dual union all select 'aaaaa' from dual) a

- 输出

1

如果我选择转换为填充值的min的长度也返回'0000000001'(这是'x'值),因为'0000000001'更小 ascii order中的'0000000005'。

select  min(lpad(length(a.f), 10, '0'))
from    (select 'x' f  from dual union all select 'aaaaa' from dual) a

- 输出

0000000001

我可以用价值本身绑定它。

select  lpad(length(a.f), 10, '0') || a.f
from    (select 'x' f  from dual union all select 'aaaaa' from dual) a

- 输出

0000000001x
0000000005aaaaa

现在我可以一起选择长度和值的最小值。

select  min(lpad(length(a.f), 10, '0') || a.f)
from    (select 'x' f  from dual union all select 'aaaaa' from dual) a

- 输出

0000000001x

现在我只能通过使用substr。

获得价值
select  substr(min(lpad(length(a.f), 10, '0') || a.f), 11, 999)
from    (select 'x' f  from dual union all select 'aaaaa' from dual) a

- 输出

x

答案 6 :(得分:0)

 select city,length(city) from (select city from station ORDER BY length(city) 
 ASC, CITY ASC)where rownum=1;


 select city,length(city) from (select city from station ORDER BY length(city) 
 DESC, CITY ASC)where rownum=1;