查询中的SQL问题。需要更好的/替代查询吗

查询中的SQL问题。需要更好的/替代查询吗,sql,oracle,select,Sql,Oracle,Select,假设我们有一张桌子 +------+ | NUMM | +------+ | 1 | | 5 | | 3 | | 8 | +------+ 我希望numm列中最近的较大数字位于numm1列中。 结果将如下所示 +-------------+ | NUMM | NUMM1| +-------------+ | 1 | 3 | | 3 | 5 | | 5 | 8 | +-------------+ 我写了一个这样的查询,它是

假设我们有一张桌子

+------+
| 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

如果您想获得直接继任者,可以使用
lead()
窗口功能:

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

如果您想获得直接继任者,可以使用
lead()
窗口功能:

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

如果是oracle,则可以使用row_number()函数进行排序,然后与[left_table]进行内部联接。排序=[right_table]。排序-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;

如果是oracle,则可以使用row_number()函数进行排序,然后与[left_table]进行内部联接。排序=[right_table]。排序-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;

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

WITH CTE_ABC
AS (
    SELECT DISTINCT NUMM
    FROM [Table]
    )
    ,CTE_XYZ
AS (
    SELECT *
    FROM (
        SELECT NUMM
            ,lead(NUMM) OVER (
                ORDER BY NUMM
                ) AS numm1
        FROM CTE_ABC
        ) A
    WHERE numm1 IS NOT NULL
    )
SELECT A.NUMM
    ,B.numm1
FROM [Table] A
LEFT JOIN CTE_XYZ B
    ON A.columnId = B.columnId
WHERE B.numm1 IS NOT NULL

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

WITH CTE_ABC
AS (
    SELECT DISTINCT NUMM
    FROM [Table]
    )
    ,CTE_XYZ
AS (
    SELECT *
    FROM (
        SELECT NUMM
            ,lead(NUMM) OVER (
                ORDER BY NUMM
                ) AS numm1
        FROM CTE_ABC
        ) A
    WHERE numm1 IS NOT NULL
    )
SELECT A.NUMM
    ,B.numm1
FROM [Table] A
LEFT JOIN CTE_XYZ B
    ON A.columnId = B.columnId
WHERE B.numm1 IS NOT NULL

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

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;
在该解决方案中,
densite_-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中的distinct操作。由于只有5条记录且没有索引的有限数据集,与之前的查询相比,前者的成本为9,后者为10。

如果没有重复的数字,Frank的答案可能是最好的,但如果您最终可以得到重复的数字,则有一种可能的解决方案:

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;
在该解决方案中,
densite_-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中的distinct操作。由于只有5条记录且没有索引的有限数据集,它的成本为9,而上一次查询的成本为10。

如果有5行怎么办?还不完全清楚您希望得到什么结果-您希望每个数字都有后续数字吗?@a_horse_,带_no_名称,我的查询可以处理任意数量的行。@FrankSchmitt我希望从列numm将位于列numm1中。现在清楚了吗?是的,清楚了。请将此信息添加到您的问题中(使用“编辑”按钮)。如果您有5行怎么办?还不是100%清楚您希望得到什么结果-您希望每个数字都有后续数字吗?@a_horse_,带_no_名称,在我的查询中,它可以处理任意数量的行。@FrankSchmitt我希望numm列中最接近的较大数字位于numm1列中。现在清楚了吗?是的,清楚了。请将此信息添加到您的问题中(使用“编辑”按钮)。与我的解决方案和此处的另一个答案相比,此答案似乎是最快的感谢方式。这似乎是一个正确的查询,但如果您的记录重复,则上述查询将失败。要处理重复记录,请参阅下面我的解决方案。我希望这会有所帮助。与我的解决方案和这里的另一个答案相比,这似乎是感谢的最快方式。这似乎是一个正确的查询,但是,如果您的记录重复出现,上述查询将失败。要处理重复记录,请参阅下面我的解决方案。我希望这会有帮助。有点贵,但是,是的,这涵盖了所有情况,查询很容易理解。感谢您使用有限的数据集,前提是我的原始查询和我刚才添加的查询之间的成本差异可以忽略不计。有点贵,但是,是的,这涵盖了所有情况,查询很容易理解。感谢您使用有限的数据集,前提是我的原始查询和我刚才添加的查询之间的成本差异可以忽略不计。