Convert Select Oracle Query To Updte for specific scenario

痞子三分冷 提交于 2020-06-17 09:32:11

问题


we are using Oracle v12+

we have a situation where we need to update status column to previous value whenever we have first RENEWAL for every code (it is functional ID and has many rows against one ID) otherwise ADD.

See sample i/o below. Data is sorted by timestamp for each ID.

Do we need specific joins to update? I have copied data to temp table for that but not getting success.

Table name: table_book_status

     Input                           CLOB
    [code]        [word]         [status]                               [timestamp]
    B000JMLBHU  book    {"name" : "Kunal", "type" : "RENEWAL"}
    B000JMLBHU  read    {"name" : "Kunal", "type" : "RENEWAL"}
    B000JMLBHU  was     {"name" : "Kunal", "type" : "MODIFY"}
    B000JMLBHU  story   {"name" : "Kunal", "type" : "ADD"}
    B000R93D4Y  with    {"name" : "RAHUL", "type" : "RENEWAL"}
    B000R93D4Y  book    {"name" : "RAHUL", "type" : "RENEWAL"}
    B000R93D4Y  story   {"name" : "RAHUL", "type" : "RENEWAL"}
    B000R93D4Y  was     {"name" : "RAHUL", "type" : "MODIFY"}
    B000R93D4Y  have    {"name" : "RAHUL", "type" : "ADD"}
    B001892DGG  was     {"name" : "Kanav", "type" : "ADD"}
    B001892DWA  was     {"name" : "Kavita", "type" : "ADD"}
    B001BXNQ2O  was     {"name" : "Keshav", "type" : "RENEWAL"}
    B001BXNQ2O  book    {"name" : "Keshav", "type" : "RENEWAL"}
    B001H55R8M  was     {"name" : "Raghav", "type" : "MODIFY"}
    B001HQHCBQ  was     {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  story   {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  bella   {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  with    {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  love    {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  zsadist {"name" : "RINA", "type" : "ADD"}


    Output


   [code]        [word]              [status]                               [timestamp]
    B000JMLBHU  book    {"name" : "Kunal", "type" : "RENEWAL"}
    B000JMLBHU  read    {"name" : "Kunal", "type" : "**MODIFY**"}
    B000JMLBHU  was     {"name" : "Kunal", "type" : "MODIFY"}
    B000JMLBHU  story   {"name" : "Kunal", "type" : "ADD"}
    B000R93D4Y  with    {"name" : "RAHUL", "type" : "RENEWAL"}
    B000R93D4Y  book    {"name" : "RAHUL", "type" : "RENEWAL"}
    B000R93D4Y  story   {"name" : "RAHUL", "type" : "**MODIFY**"}
    B000R93D4Y  was     {"name" : "RAHUL", "type" : "MODIFY"}
    B000R93D4Y  have    {"name" : "RAHUL", "type" : "ADD"}
    B001892DGG  was     {"name" : "Kanav", "type" : "ADD"}
    B001892DWA  was     {"name" : "Kavita", "type" : "ADD"}
    B001BXNQ2O  was     {"name" : "Keshav", "type" : "RENEWAL"}
    B001BXNQ2O  book    {"name" : "Keshav", "type" : "**ADD**"}
    B001H55R8M  was     {"name" : "Raghav", "type" : "MODIFY"}
    B001HQHCBQ  was     {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  story   {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  bella   {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  with    {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  love    {"name" : "RINA", "type" : "ADD"}
    B001HQHCBQ  zsadist {"name" : "RINA", "type" : "ADD"}

With the help of stackOverflow community we were able to create a select query

    SELECT code,
  status,
  CASE
    WHEN sm    = 1
    AND status = 'RENEWAL'
    THEN COALESCE(lgst, 'ADD')
    ELSE status
  END AS status1,
  timestamp
FROM
  (SELECT code,
    JSON_VALUE(status, '$.type') AS status,
    SUM(
    CASE
      WHEN JSON_VALUE(status, '$.type') = 'RENEWAL'
      THEN 1
      ELSE 0
    END) over (partition BY code order by timestamp)                                              AS sm,
    lag(JSON_VALUE(status, '$.type')) over (partition BY code order by timestamp) AS lgst,
    timestamp
  FROM table_book_status
  );

This is giving perfect result as needed but in select view, we want to get that converted to UPDATE oracle query or maybe PL/SQL. Any suggestion on that.


回答1:


A great way to update a table from a query is to use a MERGE statement. Here is an example that copies all_objects and adds a column of the number of objects that match that rows owner and type.

CREATE TABLE all_objects_2 AS
SELECT *
  FROM all_objects;

ALTER TABLE all_objects_2 add owner_and_type_ct NUMBER;

MERGE INTO all_objects_2 ao2
USING (SELECT ao.owner,
              ao.object_type,
              COUNT(*) AS ct
         FROM all_objects ao
        GROUP BY ao.owner,
                 ao.object_type) x
ON (ao2.owner = x.owner AND ao2.object_type = x.object_type)
WHEN MATCHED THEN
  UPDATE
     SET ao2.owner_and_type_ct = x.ct;

SELECT ao2.owner,
       ao2.object_name,
       ao2.object_type,
       ao2.owner_and_type_ct
  FROM all_objects_2 ao2
 WHERE rownum < 10;
/*
SYS C_TS# CLUSTER 10
SYS I_TS# INDEX 1459
SYS C_FILE#_BLOCK#  CLUSTER 10
SYS I_FILE#_BLOCK#  INDEX 1459
SYS FET$  TABLE 1592
SYS UET$  TABLE 1592
SYS SEG$  TABLE 1592
SYS UNDO$ TABLE 1592
SYS TS$ TABLE 1592
*/

You MERGE INTO [destination table] USING [your query] ON [criteria to join query to destination] and WHEN you MATCH a row you UPDATE the row with the values from the query. You can also INSERT and DELETE with a MERGE, but I'm not going to duplicate all the documentation.



来源:https://stackoverflow.com/questions/61949262/convert-select-oracle-query-to-updte-for-specific-scenario

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!