如何仅基于ROW_NUMBER()更新行?

时间:2015-05-26 08:59:13

标签: sql oracle oracle11g

这样的SQL查询:

SELECT ROW_NUMBER() OVER (PARTITION BY ID, YEAR order by ID ), ID, YEAR
from table t

给我以下查询集:

1   1000415591  2012
1   1000415591  2013
2   1000415591  2013
1   1000415591  2014
2   1000415591  2014

如何更新ROW_NUMBER()等于2的记录?此记录的其他字段相同(select distinct from table where id = 1000415591在没有distinct关键字的情况下提供3条记录),因此我只能依赖于ROW_NUMBER()值。

我需要Oracle的解决方案,因为我看到了类似于SQL-Server的东西,但它不能与Oracle合作。

4 个答案:

答案 0 :(得分:3)

您可以使用 MERGE 语句,该语句非常详细且易于理解。

例如,

MERGE INTO t s 
USING
(SELECT ROW_NUMBER() OVER (PARTITION BY ID, YEAR order by ID ) RN,
  ID,
  YEAR
FROM TABLE t
) u ON (s.id = u.id)
WHEN MATCHED THEN
  UPDATE SET YEAR = some_value WHERE u.RN = 2)
/

注意您无法合并用于加入ON子句的同一列。

答案 1 :(得分:1)

这不是更新语句,但这是如何获取要更新的2行:

SELECT * 
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY ID, YEAR order by ID ) as rn, ID, YEAR
from t )
where rn = 2

SQLFIDDLE

答案 2 :(得分:1)

尝试使用ROWID字段:

UPDATE T
SET t.year = t.year*1000
WHERE (rowid,2) in (SELECT rowid,
                           ROW_NUMBER() 
                              OVER (PARTITION BY ID, t.YEAR order by ID ) 
                    FROM T)

SQLFiddle demo

如果你需要删除ROWNUMBERS的范围,那么:

UPDATE T
SET t.year = t.year*1000
WHERE rowid in ( SELECT rowid FROM
                 ( 
                   SELECT rowid,
                           ROW_NUMBER() 
                              OVER (PARTITION BY ID, t.YEAR order by ID ) as RN
                    FROM T
                  ) T2 WHERE RN >=2 AND RN <=10
                  )

SQLFiddle demo

答案 3 :(得分:0)

当我发布这个问题时,我发现这可能是错误的方法。我可以修改表格并添加新字段。更好的解决方案是再创建一个字段IDENTITY并使用新序列中的数字从1到总行数进行更新。然后我可以根据此IDENTIY字段更新字段。

如果有人根据ROW_NUMBER()分析函数提出解决方案,我会打开这个问题。

update TABLE set NEW_ID = TABLE_SEQ.nextval 
where IDENTITY in (
    select IDENTITY from (
        select row_number() over(PARTITION BY ID, YEAR order by ID) as row_num, t.ID, t."YEAR", t.IDENTITY
        from TABLE t
    ) where row_num > 1
)