Update table using the values of other table










1















I want to clean up my table:



rid(PK) rval
----------- ----------
10 test
11 Rtest
12 dummy
13 test
14 Rtest


to remove the duplicate values from column rval, so I end up with:



rid(PK) rval
----------- ----------
10 test
11 Rtest
12 dummy


But I have another table with a foreign key relationship which uses the values I want to delete:



ruid rid(FK)
---------- ----------
1 10
2 10
3 12
4 13
5 13
6 14
7 14


so before I delete, I need to update that table to use the matching rid that I'm keeping, e.g. updating 14 to 11; so that table will end up as:



ruid rid(FK)
---------- ----------
1 10
2 10
3 12
4 10
5 10
6 11
7 11


How can I do that?










share|improve this question




























    1















    I want to clean up my table:



    rid(PK) rval
    ----------- ----------
    10 test
    11 Rtest
    12 dummy
    13 test
    14 Rtest


    to remove the duplicate values from column rval, so I end up with:



    rid(PK) rval
    ----------- ----------
    10 test
    11 Rtest
    12 dummy


    But I have another table with a foreign key relationship which uses the values I want to delete:



    ruid rid(FK)
    ---------- ----------
    1 10
    2 10
    3 12
    4 13
    5 13
    6 14
    7 14


    so before I delete, I need to update that table to use the matching rid that I'm keeping, e.g. updating 14 to 11; so that table will end up as:



    ruid rid(FK)
    ---------- ----------
    1 10
    2 10
    3 12
    4 10
    5 10
    6 11
    7 11


    How can I do that?










    share|improve this question


























      1












      1








      1


      1






      I want to clean up my table:



      rid(PK) rval
      ----------- ----------
      10 test
      11 Rtest
      12 dummy
      13 test
      14 Rtest


      to remove the duplicate values from column rval, so I end up with:



      rid(PK) rval
      ----------- ----------
      10 test
      11 Rtest
      12 dummy


      But I have another table with a foreign key relationship which uses the values I want to delete:



      ruid rid(FK)
      ---------- ----------
      1 10
      2 10
      3 12
      4 13
      5 13
      6 14
      7 14


      so before I delete, I need to update that table to use the matching rid that I'm keeping, e.g. updating 14 to 11; so that table will end up as:



      ruid rid(FK)
      ---------- ----------
      1 10
      2 10
      3 12
      4 10
      5 10
      6 11
      7 11


      How can I do that?










      share|improve this question
















      I want to clean up my table:



      rid(PK) rval
      ----------- ----------
      10 test
      11 Rtest
      12 dummy
      13 test
      14 Rtest


      to remove the duplicate values from column rval, so I end up with:



      rid(PK) rval
      ----------- ----------
      10 test
      11 Rtest
      12 dummy


      But I have another table with a foreign key relationship which uses the values I want to delete:



      ruid rid(FK)
      ---------- ----------
      1 10
      2 10
      3 12
      4 13
      5 13
      6 14
      7 14


      so before I delete, I need to update that table to use the matching rid that I'm keeping, e.g. updating 14 to 11; so that table will end up as:



      ruid rid(FK)
      ---------- ----------
      1 10
      2 10
      3 12
      4 10
      5 10
      6 11
      7 11


      How can I do that?







      sql oracle oracle11g






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 14 '18 at 15:44









      Alex Poole

      133k6107181




      133k6107181










      asked Nov 14 '18 at 14:59









      RGMRGM

      66




      66






















          1 Answer
          1






          active

          oldest

          votes


















          1














          You could use an analytic aggregate to get the lowest rid for each rval:



          min(rid) over (partition by rval)


          and use that in a subquery that joins the two tables (which I've imaginatively called t1 and t2 as you haven't given their real names) so you can see the lowest suitable rid for each ruid:



          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid;

          RUID RID MIN_RID
          ---------- ---------- ----------
          1 10 10
          2 10 10
          3 12 12
          4 13 10
          5 13 10
          6 14 11
          7 14 11


          You can then use that in a merge statement:



          merge into t2
          using (
          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid
          ) y
          on (t2.ruid = y.ruid)
          when matched then update set t2.rid = y.min_rid
          where t2.rid != y.min_rid;

          4 rows merged.

          select * from t2;

          RUID RID
          ---------- ----------
          1 10
          2 10
          3 12
          4 10
          5 10
          6 11
          7 11


          Once you've done that you can remove the redundant PK values:



          delete from t1
          where exists (select * from t1 x where x.rval = t1.rval and x.rid < t1.rid);

          2 rows deleted.

          select * from t1;

          RID RVAL
          ---------- -----
          10 test
          11 Rtest
          12 dummy



          Id ruid is not unique, and there is no other unique key you can include in the statement, then you can't really use a merge - you can't refer to rid in the on clause as that's the column you're updating.



          You could do a correlated update instead:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );


          That will update every row; if you have a lot of data and/or a small proportion need to change then you can add a filter to only update those:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          )
          where rid != (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );





          share|improve this answer

























          • Thank you, it worked well!!! And thank you for formatting my question.

            – RGM
            Nov 14 '18 at 15:44












          • Will duplicate RUIDs always have the same RID?

            – Alex Poole
            Nov 15 '18 at 13:43











          • Duplicate RUID can have same and different both RID. for same RUID-RID I can use DISTINCT but if RID is not same, what to do in that case?

            – RGM
            Nov 15 '18 at 13:46












          • Can anyone suggest solution for duplicate RUID values?

            – RGM
            Nov 15 '18 at 14:26











          • @RGM - I've added a solution with a correlated update.

            – Alex Poole
            Nov 15 '18 at 15:06










          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53303101%2fupdate-table-using-the-values-of-other-table%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          You could use an analytic aggregate to get the lowest rid for each rval:



          min(rid) over (partition by rval)


          and use that in a subquery that joins the two tables (which I've imaginatively called t1 and t2 as you haven't given their real names) so you can see the lowest suitable rid for each ruid:



          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid;

          RUID RID MIN_RID
          ---------- ---------- ----------
          1 10 10
          2 10 10
          3 12 12
          4 13 10
          5 13 10
          6 14 11
          7 14 11


          You can then use that in a merge statement:



          merge into t2
          using (
          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid
          ) y
          on (t2.ruid = y.ruid)
          when matched then update set t2.rid = y.min_rid
          where t2.rid != y.min_rid;

          4 rows merged.

          select * from t2;

          RUID RID
          ---------- ----------
          1 10
          2 10
          3 12
          4 10
          5 10
          6 11
          7 11


          Once you've done that you can remove the redundant PK values:



          delete from t1
          where exists (select * from t1 x where x.rval = t1.rval and x.rid < t1.rid);

          2 rows deleted.

          select * from t1;

          RID RVAL
          ---------- -----
          10 test
          11 Rtest
          12 dummy



          Id ruid is not unique, and there is no other unique key you can include in the statement, then you can't really use a merge - you can't refer to rid in the on clause as that's the column you're updating.



          You could do a correlated update instead:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );


          That will update every row; if you have a lot of data and/or a small proportion need to change then you can add a filter to only update those:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          )
          where rid != (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );





          share|improve this answer

























          • Thank you, it worked well!!! And thank you for formatting my question.

            – RGM
            Nov 14 '18 at 15:44












          • Will duplicate RUIDs always have the same RID?

            – Alex Poole
            Nov 15 '18 at 13:43











          • Duplicate RUID can have same and different both RID. for same RUID-RID I can use DISTINCT but if RID is not same, what to do in that case?

            – RGM
            Nov 15 '18 at 13:46












          • Can anyone suggest solution for duplicate RUID values?

            – RGM
            Nov 15 '18 at 14:26











          • @RGM - I've added a solution with a correlated update.

            – Alex Poole
            Nov 15 '18 at 15:06















          1














          You could use an analytic aggregate to get the lowest rid for each rval:



          min(rid) over (partition by rval)


          and use that in a subquery that joins the two tables (which I've imaginatively called t1 and t2 as you haven't given their real names) so you can see the lowest suitable rid for each ruid:



          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid;

          RUID RID MIN_RID
          ---------- ---------- ----------
          1 10 10
          2 10 10
          3 12 12
          4 13 10
          5 13 10
          6 14 11
          7 14 11


          You can then use that in a merge statement:



          merge into t2
          using (
          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid
          ) y
          on (t2.ruid = y.ruid)
          when matched then update set t2.rid = y.min_rid
          where t2.rid != y.min_rid;

          4 rows merged.

          select * from t2;

          RUID RID
          ---------- ----------
          1 10
          2 10
          3 12
          4 10
          5 10
          6 11
          7 11


          Once you've done that you can remove the redundant PK values:



          delete from t1
          where exists (select * from t1 x where x.rval = t1.rval and x.rid < t1.rid);

          2 rows deleted.

          select * from t1;

          RID RVAL
          ---------- -----
          10 test
          11 Rtest
          12 dummy



          Id ruid is not unique, and there is no other unique key you can include in the statement, then you can't really use a merge - you can't refer to rid in the on clause as that's the column you're updating.



          You could do a correlated update instead:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );


          That will update every row; if you have a lot of data and/or a small proportion need to change then you can add a filter to only update those:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          )
          where rid != (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );





          share|improve this answer

























          • Thank you, it worked well!!! And thank you for formatting my question.

            – RGM
            Nov 14 '18 at 15:44












          • Will duplicate RUIDs always have the same RID?

            – Alex Poole
            Nov 15 '18 at 13:43











          • Duplicate RUID can have same and different both RID. for same RUID-RID I can use DISTINCT but if RID is not same, what to do in that case?

            – RGM
            Nov 15 '18 at 13:46












          • Can anyone suggest solution for duplicate RUID values?

            – RGM
            Nov 15 '18 at 14:26











          • @RGM - I've added a solution with a correlated update.

            – Alex Poole
            Nov 15 '18 at 15:06













          1












          1








          1







          You could use an analytic aggregate to get the lowest rid for each rval:



          min(rid) over (partition by rval)


          and use that in a subquery that joins the two tables (which I've imaginatively called t1 and t2 as you haven't given their real names) so you can see the lowest suitable rid for each ruid:



          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid;

          RUID RID MIN_RID
          ---------- ---------- ----------
          1 10 10
          2 10 10
          3 12 12
          4 13 10
          5 13 10
          6 14 11
          7 14 11


          You can then use that in a merge statement:



          merge into t2
          using (
          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid
          ) y
          on (t2.ruid = y.ruid)
          when matched then update set t2.rid = y.min_rid
          where t2.rid != y.min_rid;

          4 rows merged.

          select * from t2;

          RUID RID
          ---------- ----------
          1 10
          2 10
          3 12
          4 10
          5 10
          6 11
          7 11


          Once you've done that you can remove the redundant PK values:



          delete from t1
          where exists (select * from t1 x where x.rval = t1.rval and x.rid < t1.rid);

          2 rows deleted.

          select * from t1;

          RID RVAL
          ---------- -----
          10 test
          11 Rtest
          12 dummy



          Id ruid is not unique, and there is no other unique key you can include in the statement, then you can't really use a merge - you can't refer to rid in the on clause as that's the column you're updating.



          You could do a correlated update instead:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );


          That will update every row; if you have a lot of data and/or a small proportion need to change then you can add a filter to only update those:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          )
          where rid != (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );





          share|improve this answer















          You could use an analytic aggregate to get the lowest rid for each rval:



          min(rid) over (partition by rval)


          and use that in a subquery that joins the two tables (which I've imaginatively called t1 and t2 as you haven't given their real names) so you can see the lowest suitable rid for each ruid:



          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid;

          RUID RID MIN_RID
          ---------- ---------- ----------
          1 10 10
          2 10 10
          3 12 12
          4 13 10
          5 13 10
          6 14 11
          7 14 11


          You can then use that in a merge statement:



          merge into t2
          using (
          select t2.ruid, t2.rid, x.min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          join t2 on t2.rid = x.rid
          ) y
          on (t2.ruid = y.ruid)
          when matched then update set t2.rid = y.min_rid
          where t2.rid != y.min_rid;

          4 rows merged.

          select * from t2;

          RUID RID
          ---------- ----------
          1 10
          2 10
          3 12
          4 10
          5 10
          6 11
          7 11


          Once you've done that you can remove the redundant PK values:



          delete from t1
          where exists (select * from t1 x where x.rval = t1.rval and x.rid < t1.rid);

          2 rows deleted.

          select * from t1;

          RID RVAL
          ---------- -----
          10 test
          11 Rtest
          12 dummy



          Id ruid is not unique, and there is no other unique key you can include in the statement, then you can't really use a merge - you can't refer to rid in the on clause as that's the column you're updating.



          You could do a correlated update instead:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );


          That will update every row; if you have a lot of data and/or a small proportion need to change then you can add a filter to only update those:



          update t2
          set rid = (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          )
          where rid != (
          select min_rid
          from (
          select rid, min(rid) over (partition by rval) as min_rid from t1
          ) x
          where x.rid = t2.rid
          );






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 15 '18 at 15:05

























          answered Nov 14 '18 at 15:36









          Alex PooleAlex Poole

          133k6107181




          133k6107181












          • Thank you, it worked well!!! And thank you for formatting my question.

            – RGM
            Nov 14 '18 at 15:44












          • Will duplicate RUIDs always have the same RID?

            – Alex Poole
            Nov 15 '18 at 13:43











          • Duplicate RUID can have same and different both RID. for same RUID-RID I can use DISTINCT but if RID is not same, what to do in that case?

            – RGM
            Nov 15 '18 at 13:46












          • Can anyone suggest solution for duplicate RUID values?

            – RGM
            Nov 15 '18 at 14:26











          • @RGM - I've added a solution with a correlated update.

            – Alex Poole
            Nov 15 '18 at 15:06

















          • Thank you, it worked well!!! And thank you for formatting my question.

            – RGM
            Nov 14 '18 at 15:44












          • Will duplicate RUIDs always have the same RID?

            – Alex Poole
            Nov 15 '18 at 13:43











          • Duplicate RUID can have same and different both RID. for same RUID-RID I can use DISTINCT but if RID is not same, what to do in that case?

            – RGM
            Nov 15 '18 at 13:46












          • Can anyone suggest solution for duplicate RUID values?

            – RGM
            Nov 15 '18 at 14:26











          • @RGM - I've added a solution with a correlated update.

            – Alex Poole
            Nov 15 '18 at 15:06
















          Thank you, it worked well!!! And thank you for formatting my question.

          – RGM
          Nov 14 '18 at 15:44






          Thank you, it worked well!!! And thank you for formatting my question.

          – RGM
          Nov 14 '18 at 15:44














          Will duplicate RUIDs always have the same RID?

          – Alex Poole
          Nov 15 '18 at 13:43





          Will duplicate RUIDs always have the same RID?

          – Alex Poole
          Nov 15 '18 at 13:43













          Duplicate RUID can have same and different both RID. for same RUID-RID I can use DISTINCT but if RID is not same, what to do in that case?

          – RGM
          Nov 15 '18 at 13:46






          Duplicate RUID can have same and different both RID. for same RUID-RID I can use DISTINCT but if RID is not same, what to do in that case?

          – RGM
          Nov 15 '18 at 13:46














          Can anyone suggest solution for duplicate RUID values?

          – RGM
          Nov 15 '18 at 14:26





          Can anyone suggest solution for duplicate RUID values?

          – RGM
          Nov 15 '18 at 14:26













          @RGM - I've added a solution with a correlated update.

          – Alex Poole
          Nov 15 '18 at 15:06





          @RGM - I've added a solution with a correlated update.

          – Alex Poole
          Nov 15 '18 at 15:06



















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53303101%2fupdate-table-using-the-values-of-other-table%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Use pre created SQLite database for Android project in kotlin

          Darth Vader #20

          Ondo