oracle 将前一行中的前一列与下一行中的下一列进行比较

kokeuurv  于 2023-02-07  发布在  Oracle
关注(0)|答案(4)|浏览(259)

我的代码是:

with x as 
(
    select 1 col from dual union all
    select 2 col from dual union all
    select 8 col from dual union all
    select 4 col from dual union all
    select 3 col from dual union all
    select 2 col from dual
)
select col col1, col col2, col col3, rownum
from x 
where col2.ROWNUM > col1.ROWNUM -1 
  and col2.ROWNUM > col3ROWNUM +1 ;

我想比较col2.ROWNUM > col1.ROWNUM -1 and col2.ROWNUM > col3ROWNUM + 1,但这不起作用,并且出现错误
ORA-01747:用户、表、列、表、列或列说明无效
01747. 00000-"无效的用户.表.列,表.列,或列说明"

  • 原因:
  • 行动:
    行错误:10色谱柱:13
    请帮帮我
deyfvvtc

deyfvvtc1#

你好像出了点问题。
该CTE的结果是一个单列 * 表 *,其中只有一列名为col,没有其他列。

SQL> with x as (
  2  select 1 col from dual union all  --> in UNION, all columns are
  3  select 2 col from dual union all      named by column name(s) from the 
  4  select 8 col from dual union all      first SELECT statement
  5  select 4 col from dual union all
  6  select 3 col from dual union all
  7  select 2 col from dual)
  8  select x.*, rownum
  9  from x;

       COL     ROWNUM
---------- ----------
         1          1
         2          2
         8          3
         4          4
         3          5
         2          6

6 rows selected.

SQL>

因此,您编写的where子句没有任何意义,也许您应该解释一下您真正拥有的是什么,应该应用于源数据的规则以及您希望得到的结果。
根据您放入标题中的文本:
比较前一行中的前一列与下一行中的下一列
也许您会对laglead分析函数感兴趣,这些函数允许您 * 比较 * 相邻行中的值(注意NULL值;我没有)。例如:

SQL> with x as (
  2    select 1 col from dual union all
  3    select 2 col from dual union all
  4    select 8 col from dual union all
  5    select 4 col from dual union all
  6    select 3 col from dual union all
  7    select 2 col from dual
  8    ),
  9  temp as
 10    (select col,
 11            rownum as rn
 12     from x
 13    ),
 14  temp2 as
 15    (select
 16       rn,
 17       col as this_row,
 18       lag(col)  over (order by rn) as previous_row,
 19       lead(col) over (order by rn) as next_row
 20     from temp
 21    )
 22  select this_row,
 23    previous_row,
 24    next_row,
 25    --
 26    case when this_row < previous_row then 'This < previous'
 27         when this_row < next_row     then 'This < next'
 28         else 'something else'
 29    end as result
 30  from temp2
 31  order by rn;

结果:

THIS_ROW PREVIOUS_ROW   NEXT_ROW RESULT
---------- ------------ ---------- ---------------
         1                       2 This < next
         2            1          8 This < next
         8            2          4 something else
         4            8          3 This < previous
         3            4          2 This < previous
         2            3            This < previous

6 rows selected.

SQL>
6tdlim6h

6tdlim6h2#

使用lead或lag函数。但是,请不要将rownum用于此类目的。Rownum仅指示在数据库中找到行的顺序,除了限制获取的行数外,不能用于其他目的,例如,当rownum〈=1时,可以确保不会出现too_many_rows异常。尽管如此,如果在查询中获取伪列rownum,给予它一个别名,以便以后可以使用该值。此外,col2.ROWNUM或col1.ROWNUM应该是什么意思?这一点并不清楚。col 1和col 2是两列,它们没有属性rownum。以下内容可能对将来的分析查询有所帮助:https://oracle-base.com/articles/misc/lag-lead-analytic-functions
而且,如果你希望得到一个工作的SQL,请清楚地解释你希望实现什么,因为我还没有真正理解代码的目的是什么。
使用rownum而不会出错的一种方法:

with x as (
select 1 col from dual union all
select 2 col from dual union all
select 8 col from dual union all
select 4 col from dual union all
select 3 col from dual union all
select 2 col from dual)

,x2 as(select col col 1,col col 2,col col 3,rownum rn from x)select * from x2其中rn在2和3之间--- rownum不能用于这样的条件!!!;
或者,为了确保只从满足给定条件的表中获取第一行:

select x_col1, x_col2 into v_col1, v_col2
from x_table
where ... --- logical conditions
  and rownum<=1; --- rownum <= 1 avoids too_many_rows_exception if several rows satisfy the logical conditions given before
pb3skfrl

pb3skfrl3#

在Oracle中,除非使用ORDER BY子句,否则结果集具有不确定的顺序(即,它们是无序的)。因此,如果您有物理表,则需要另一列来提供顺序(而不是依赖ROWNUM伪列,后者可能会导致意外行为):

CREATE TABLE x (order_id, col) AS
  SELECT 1, 1 FROM DUAL UNION ALL
  SELECT 2, 2 FROM DUAL UNION ALL
  SELECT 3, 8 FROM DUAL UNION ALL
  SELECT 4, 4 FROM DUAL UNION ALL
  SELECT 5, 3 FROM DUAL UNION ALL
  SELECT 6, 2 FROM DUAL;

如果您想找到连续向上的行,那么可以使用MATCH_RECOGNIZE进行逐行模式匹配:

SELECT *
FROM   x
MATCH_RECOGNIZE(
  ORDER BY order_id
  MEASURES
    any_row.col     AS col1,
    FIRST(up.col)   AS col2,
    LAST(up.col)    AS col3,
    FIRST(order_id) AS start_order_id
  PATTERN ( any_row up{2} )
  DEFINE up AS ( col > PREV(col) )
)

LEAD解析函数:

SELECT *
FROM   (
  SELECT col AS col1,
         LEAD(col, 1) OVER (ORDER BY order_id) AS col2,
         LEAD(col, 2) OVER (ORDER BY order_id) AS col3,
         order_id
  FROM   x
)
WHERE  col2 > col1
AND    col3 > col2;

两者都输出:
| COL1|COL2|COL3|开始订单ID|
| - ------|- ------|- ------|- ------|
| 1个|第二章|八个|1个|
fiddle

2j4z5cfb

2j4z5cfb4#

看起来您想查找列值大于上一行和下一行的值的行。如果是这样,您可以尝试以下操作:

WITH 
    tbl (ID, COL) AS    -- Sample data (ID column is just to preserve order of the rows)
      (
          Select 1, 1 From Dual Union All
          Select 2, 2 From Dual Union All
          Select 3, 8 From Dual Union All
          Select 4, 4 From Dual Union All
          Select 5, 3 From Dual Union All
          Select 6, 2 From DUAL
      )
Select    ID, COL, CASE WHEN COL > LAG(COL, 1) OVER(Order By ID) And COL > LEAD(COL, 1) OVER(Order By ID) THEN 'YES' END "BIGGER_THAN_PREV_AND_NEXT"
From      tbl
Order By  ID

        ID        COL BIGGER_THAN_PREV_AND_NEXT
---------- ---------- -------------------------
         1          1                           
         2          2                           
         3          8 YES                       
         4          4                           
         5          3                           
         6          2

...使用稍有不同的样本数据,这将找到满足条件的其他行...

WITH 
    tbl (ID, COL) AS    -- Sample data (ID column is just to preserve order of the rows)
      (
          Select 1, 1 From Dual Union All
          Select 2, 2 From Dual Union All
          Select 3, 8 From Dual Union All
          Select 4, 4 From Dual Union All
          Select 5, 5 From Dual Union All   -- value of COL changed from 3 to 5
          Select 6, 2 From DUAL
      )
Select    ID, COL, CASE WHEN COL > LAG(COL, 1) OVER(Order By ID) And COL > LEAD(COL, 1) OVER(Order By ID) THEN 'YES' END "BIGGER_THAN_PREV_AND_NEXT"
From      tbl
Order By  ID

        ID        COL BIGGER_THAN_PREV_AND_NEXT
---------- ---------- -------------------------
         1          1                           
         2          2                           
         3          8 YES                       
         4          4                           
         5          5 YES                       
         6          2

或没有ID -使用ROWNUM(如您的问题),-不建议,尽管...

WITH 
    tbl (COL) AS    -- Sample data (without ID column)
      (
          Select 1 From Dual Union All
          Select 2 From Dual Union All
          Select 8 From Dual Union All
          Select 4 From Dual Union All
          Select 5 From Dual Union All   
          Select 2 From DUAL
      )
Select    COL, CASE WHEN COL > LAG(COL, 1) OVER(Order By ROWNUM) And COL > LEAD(COL, 1) OVER(Order By ROWNUM) THEN 'YES' END "BIGGER_THAN_PREV_AND_NEXT"
From      tbl

       COL BIGGER_THAN_PREV_AND_NEXT
---------- -------------------------
         1                           
         2                           
         8 YES                       
         4                           
         5 YES                       
         2

添加到查询中的任何Order By子句都可能更改ROWNUM值和结果...

相关问题