假设我们有一张桌子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
答案 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。