关于查询的SQL问题。需要更好/备用查询

时间:2015-09-08 10:00:08

标签: sql oracle select

假设我们有一张桌子T

+------+
| NUMM |
+------+
|   1  |
|   5  |
|   3  |
|   8  |
+------+ 

我希望列numm中最接近的较大数字在列numm1中。 结果将如下所示

+-------------+
| NUMM | NUMM1|
+-------------+
|   1  |   3  |
|   3  |   5  |
|   5  |   8  |
+-------------+     

我写了一个像这样的查询,它的确有效。但我想知道是否有更好的解决方法。

select numm, numm + min(dif) as numm1
  from (select distinct a.numm numm, b.numm numm1, b.numm - a.numm dif
         from (select *
              from T
             where numm != (select max(numm) from T )) a
      join T b
        on 1 = 1)
where dif > 0
group by numm

4 个答案:

答案 0 :(得分:3)

如果您想获得直接后继者,可以使用lead()窗口函数:

select * from (
  select 
    numm, 
    lead(numm) over (order by numm) as numm1 
  from t  
) 
where numm1 is not null
order by numm;

答案 1 :(得分:1)

如果是oracle,你可以使用row_number()函数进行排名,然后使用[left_table]进行内连接.rank = [right_table] .rank - 1:

SELECT a.numm,
       b.numm
FROM
  (SELECT numm, row_number() over(order by numm) AS rank FROM pn_test) a
INNER JOIN
  (SELECT numm, row_number() over(order by numm) AS rank FROM pn_test) b
ON a.rank = b.rank - 1;

答案 2 :(得分:1)

如果您的表中有重复记录,请尝试以下查询:

echo $query->studentID;

答案 3 :(得分:1)

弗兰克的答案可能是最好的,如果没有重复的数字,但如果你最终可以得到重复,这是一个可能的解决方案:

with t1 as (
 select numm
      , dense_rank() over (order by numm) rnk
   from t
)
select t1.numm
     , t2.numm numm1
  from t1
  join (select distinct numm, rnk-1 rnk from t1) t2
    on t1.rnk = t2.rnk;

在此解决方案中,DENSE_RANK分析函数首先在T1中使用,以便为每个不同的NUMM提供一个序列号(RNK)。在第二阶段,T1将RNK连接到来自t1的不同numm和rnk-1值集。

为了获得更好的性能,这可能会起到作用:

with t1 as (
 select numm
      , dense_rank() over (order by numm) rnk
      , row_number() over (partition by numm order by rownum) ord
   from t
)
select t1.numm
     , t2.numm numm1
  from t1
  join t1 t2
    on t1.rnk = t2.rnk-1
   and t2.ord = 1;

这里我添加了一种方法,可以将每个numm的一条记录抓取到子因子查询中,并消除了T2中的不同操作。对于仅有5条记录且没有索引的有限数据集,它的成本为9,而先前查询的成本为10。