Enabling Duplicates in WHERE … IN?












3















I want to use a simple query to decrement a value in a table like so:



UPDATE `Table`
SET `foo` = `foo` - 1
WHERE `bar` IN (1, 2, 3, 4, 5)


This works great in examples such as the above, where the IN list contains only unique values, so each matching row has its foo column decremented by 1.



The problem is when the list contains duplicates, for example:



UPDATE `Table`
SET `foo` = `foo` - 1
WHERE `bar` IN (1, 3, 3, 3, 5)


In this case I would like the row where bar is 3 to be decremented three times (or by three), and 1 and 5 to be decremented by 1.



Is there a way to change the behaviour, or an alternative query that I can use where I can get the desired behaviour?



I'm specifically using MySQL 5.7, in case there are any MySQL specific workarounds that are helpful.



Update: I'm building the query in a scripting language, so feel free to provide solutions that perform any additional processing prior to running the query (perhaps as pseudo code, to be as useful to as many as possible?). I don't mind doing it this way, I just want to keep the query as simple as possible while giving the expected result.










share|improve this question




















  • 1





    Where does your list come from? Is it an embedded query, do you have three rows where bar = 3, or one?

    – Derrick Moeller
    Nov 14 '18 at 18:12






  • 2





    Also, is it not set foo = foo - 1 instead of set foo - 1? Or is it the alternate way of writing I am unaware about?

    – vivek_23
    Nov 14 '18 at 18:15













  • What does SET foo - 1 do?

    – Eric
    Nov 14 '18 at 18:25






  • 1





    @vivek_23 you're absolutely right, that's just a typo on my part, I've corrected my original post!

    – Haravikk
    Nov 14 '18 at 18:51













  • @DerrickMoeller I'm building the query in PHP so I have full access to the list if a solution requires that, though it may be best to keep it as some kind of pseudo code.

    – Haravikk
    Nov 14 '18 at 18:51


















3















I want to use a simple query to decrement a value in a table like so:



UPDATE `Table`
SET `foo` = `foo` - 1
WHERE `bar` IN (1, 2, 3, 4, 5)


This works great in examples such as the above, where the IN list contains only unique values, so each matching row has its foo column decremented by 1.



The problem is when the list contains duplicates, for example:



UPDATE `Table`
SET `foo` = `foo` - 1
WHERE `bar` IN (1, 3, 3, 3, 5)


In this case I would like the row where bar is 3 to be decremented three times (or by three), and 1 and 5 to be decremented by 1.



Is there a way to change the behaviour, or an alternative query that I can use where I can get the desired behaviour?



I'm specifically using MySQL 5.7, in case there are any MySQL specific workarounds that are helpful.



Update: I'm building the query in a scripting language, so feel free to provide solutions that perform any additional processing prior to running the query (perhaps as pseudo code, to be as useful to as many as possible?). I don't mind doing it this way, I just want to keep the query as simple as possible while giving the expected result.










share|improve this question




















  • 1





    Where does your list come from? Is it an embedded query, do you have three rows where bar = 3, or one?

    – Derrick Moeller
    Nov 14 '18 at 18:12






  • 2





    Also, is it not set foo = foo - 1 instead of set foo - 1? Or is it the alternate way of writing I am unaware about?

    – vivek_23
    Nov 14 '18 at 18:15













  • What does SET foo - 1 do?

    – Eric
    Nov 14 '18 at 18:25






  • 1





    @vivek_23 you're absolutely right, that's just a typo on my part, I've corrected my original post!

    – Haravikk
    Nov 14 '18 at 18:51













  • @DerrickMoeller I'm building the query in PHP so I have full access to the list if a solution requires that, though it may be best to keep it as some kind of pseudo code.

    – Haravikk
    Nov 14 '18 at 18:51
















3












3








3


2






I want to use a simple query to decrement a value in a table like so:



UPDATE `Table`
SET `foo` = `foo` - 1
WHERE `bar` IN (1, 2, 3, 4, 5)


This works great in examples such as the above, where the IN list contains only unique values, so each matching row has its foo column decremented by 1.



The problem is when the list contains duplicates, for example:



UPDATE `Table`
SET `foo` = `foo` - 1
WHERE `bar` IN (1, 3, 3, 3, 5)


In this case I would like the row where bar is 3 to be decremented three times (or by three), and 1 and 5 to be decremented by 1.



Is there a way to change the behaviour, or an alternative query that I can use where I can get the desired behaviour?



I'm specifically using MySQL 5.7, in case there are any MySQL specific workarounds that are helpful.



Update: I'm building the query in a scripting language, so feel free to provide solutions that perform any additional processing prior to running the query (perhaps as pseudo code, to be as useful to as many as possible?). I don't mind doing it this way, I just want to keep the query as simple as possible while giving the expected result.










share|improve this question
















I want to use a simple query to decrement a value in a table like so:



UPDATE `Table`
SET `foo` = `foo` - 1
WHERE `bar` IN (1, 2, 3, 4, 5)


This works great in examples such as the above, where the IN list contains only unique values, so each matching row has its foo column decremented by 1.



The problem is when the list contains duplicates, for example:



UPDATE `Table`
SET `foo` = `foo` - 1
WHERE `bar` IN (1, 3, 3, 3, 5)


In this case I would like the row where bar is 3 to be decremented three times (or by three), and 1 and 5 to be decremented by 1.



Is there a way to change the behaviour, or an alternative query that I can use where I can get the desired behaviour?



I'm specifically using MySQL 5.7, in case there are any MySQL specific workarounds that are helpful.



Update: I'm building the query in a scripting language, so feel free to provide solutions that perform any additional processing prior to running the query (perhaps as pseudo code, to be as useful to as many as possible?). I don't mind doing it this way, I just want to keep the query as simple as possible while giving the expected result.







mysql sql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 18:50







Haravikk

















asked Nov 14 '18 at 18:07









HaravikkHaravikk

1,35711432




1,35711432








  • 1





    Where does your list come from? Is it an embedded query, do you have three rows where bar = 3, or one?

    – Derrick Moeller
    Nov 14 '18 at 18:12






  • 2





    Also, is it not set foo = foo - 1 instead of set foo - 1? Or is it the alternate way of writing I am unaware about?

    – vivek_23
    Nov 14 '18 at 18:15













  • What does SET foo - 1 do?

    – Eric
    Nov 14 '18 at 18:25






  • 1





    @vivek_23 you're absolutely right, that's just a typo on my part, I've corrected my original post!

    – Haravikk
    Nov 14 '18 at 18:51













  • @DerrickMoeller I'm building the query in PHP so I have full access to the list if a solution requires that, though it may be best to keep it as some kind of pseudo code.

    – Haravikk
    Nov 14 '18 at 18:51
















  • 1





    Where does your list come from? Is it an embedded query, do you have three rows where bar = 3, or one?

    – Derrick Moeller
    Nov 14 '18 at 18:12






  • 2





    Also, is it not set foo = foo - 1 instead of set foo - 1? Or is it the alternate way of writing I am unaware about?

    – vivek_23
    Nov 14 '18 at 18:15













  • What does SET foo - 1 do?

    – Eric
    Nov 14 '18 at 18:25






  • 1





    @vivek_23 you're absolutely right, that's just a typo on my part, I've corrected my original post!

    – Haravikk
    Nov 14 '18 at 18:51













  • @DerrickMoeller I'm building the query in PHP so I have full access to the list if a solution requires that, though it may be best to keep it as some kind of pseudo code.

    – Haravikk
    Nov 14 '18 at 18:51










1




1





Where does your list come from? Is it an embedded query, do you have three rows where bar = 3, or one?

– Derrick Moeller
Nov 14 '18 at 18:12





Where does your list come from? Is it an embedded query, do you have three rows where bar = 3, or one?

– Derrick Moeller
Nov 14 '18 at 18:12




2




2





Also, is it not set foo = foo - 1 instead of set foo - 1? Or is it the alternate way of writing I am unaware about?

– vivek_23
Nov 14 '18 at 18:15







Also, is it not set foo = foo - 1 instead of set foo - 1? Or is it the alternate way of writing I am unaware about?

– vivek_23
Nov 14 '18 at 18:15















What does SET foo - 1 do?

– Eric
Nov 14 '18 at 18:25





What does SET foo - 1 do?

– Eric
Nov 14 '18 at 18:25




1




1





@vivek_23 you're absolutely right, that's just a typo on my part, I've corrected my original post!

– Haravikk
Nov 14 '18 at 18:51







@vivek_23 you're absolutely right, that's just a typo on my part, I've corrected my original post!

– Haravikk
Nov 14 '18 at 18:51















@DerrickMoeller I'm building the query in PHP so I have full access to the list if a solution requires that, though it may be best to keep it as some kind of pseudo code.

– Haravikk
Nov 14 '18 at 18:51







@DerrickMoeller I'm building the query in PHP so I have full access to the list if a solution requires that, though it may be best to keep it as some kind of pseudo code.

– Haravikk
Nov 14 '18 at 18:51














3 Answers
3






active

oldest

votes


















1














If you can process your original list first to get the counts, you could dynamically construct this kind of query:



UPDATE `Table`
SET `foo` = `foo` - CASE `bar` WHEN 1 THEN 1 WHEN 3 THEN 3 WHEN 5 THEN 1 ELSE 0 END
WHERE `bar` IN (1, 3, 5)
;


Note: the ELSE is just being thorough/paranoid; the WHERE should prevent it from ever getting that far.






share|improve this answer































    0














    There is an example might be beneficial for your purpose:



    create table #temp (value int)
    create table #mainTable (id int, mainValue int)

    insert into #temp (value) values (1),(3),(3),(3),(4)
    insert into #mainTable values (1,5),(2,5),(3,5),(4,5)

    select value,count(*) as AddValue
    into #otherTemp
    from #temp t
    group by value

    update m
    set mainValue = m.mainValue+ ot.AddValue
    from #otherTemp ot
    inner join #mainTable m on m.id=ot.value

    select * from #mainTable





    share|improve this answer































      0














      This is a little tricky, but you can do it by aggregating first:



      update table t join
      (select bar, count(*) as factor
      from (select 1 as bar union all select 3 as bar union all select 3 as bar union all select 3 as bar union all select 5
      ) b
      ) b
      on t.bar = b.bar
      t.foo = t.foo - bar.factor;





      share|improve this answer























        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%2f53306361%2fenabling-duplicates-in-where-in%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        1














        If you can process your original list first to get the counts, you could dynamically construct this kind of query:



        UPDATE `Table`
        SET `foo` = `foo` - CASE `bar` WHEN 1 THEN 1 WHEN 3 THEN 3 WHEN 5 THEN 1 ELSE 0 END
        WHERE `bar` IN (1, 3, 5)
        ;


        Note: the ELSE is just being thorough/paranoid; the WHERE should prevent it from ever getting that far.






        share|improve this answer




























          1














          If you can process your original list first to get the counts, you could dynamically construct this kind of query:



          UPDATE `Table`
          SET `foo` = `foo` - CASE `bar` WHEN 1 THEN 1 WHEN 3 THEN 3 WHEN 5 THEN 1 ELSE 0 END
          WHERE `bar` IN (1, 3, 5)
          ;


          Note: the ELSE is just being thorough/paranoid; the WHERE should prevent it from ever getting that far.






          share|improve this answer


























            1












            1








            1







            If you can process your original list first to get the counts, you could dynamically construct this kind of query:



            UPDATE `Table`
            SET `foo` = `foo` - CASE `bar` WHEN 1 THEN 1 WHEN 3 THEN 3 WHEN 5 THEN 1 ELSE 0 END
            WHERE `bar` IN (1, 3, 5)
            ;


            Note: the ELSE is just being thorough/paranoid; the WHERE should prevent it from ever getting that far.






            share|improve this answer













            If you can process your original list first to get the counts, you could dynamically construct this kind of query:



            UPDATE `Table`
            SET `foo` = `foo` - CASE `bar` WHEN 1 THEN 1 WHEN 3 THEN 3 WHEN 5 THEN 1 ELSE 0 END
            WHERE `bar` IN (1, 3, 5)
            ;


            Note: the ELSE is just being thorough/paranoid; the WHERE should prevent it from ever getting that far.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 14 '18 at 19:45









            UueerdoUueerdo

            11.9k1816




            11.9k1816

























                0














                There is an example might be beneficial for your purpose:



                create table #temp (value int)
                create table #mainTable (id int, mainValue int)

                insert into #temp (value) values (1),(3),(3),(3),(4)
                insert into #mainTable values (1,5),(2,5),(3,5),(4,5)

                select value,count(*) as AddValue
                into #otherTemp
                from #temp t
                group by value

                update m
                set mainValue = m.mainValue+ ot.AddValue
                from #otherTemp ot
                inner join #mainTable m on m.id=ot.value

                select * from #mainTable





                share|improve this answer




























                  0














                  There is an example might be beneficial for your purpose:



                  create table #temp (value int)
                  create table #mainTable (id int, mainValue int)

                  insert into #temp (value) values (1),(3),(3),(3),(4)
                  insert into #mainTable values (1,5),(2,5),(3,5),(4,5)

                  select value,count(*) as AddValue
                  into #otherTemp
                  from #temp t
                  group by value

                  update m
                  set mainValue = m.mainValue+ ot.AddValue
                  from #otherTemp ot
                  inner join #mainTable m on m.id=ot.value

                  select * from #mainTable





                  share|improve this answer


























                    0












                    0








                    0







                    There is an example might be beneficial for your purpose:



                    create table #temp (value int)
                    create table #mainTable (id int, mainValue int)

                    insert into #temp (value) values (1),(3),(3),(3),(4)
                    insert into #mainTable values (1,5),(2,5),(3,5),(4,5)

                    select value,count(*) as AddValue
                    into #otherTemp
                    from #temp t
                    group by value

                    update m
                    set mainValue = m.mainValue+ ot.AddValue
                    from #otherTemp ot
                    inner join #mainTable m on m.id=ot.value

                    select * from #mainTable





                    share|improve this answer













                    There is an example might be beneficial for your purpose:



                    create table #temp (value int)
                    create table #mainTable (id int, mainValue int)

                    insert into #temp (value) values (1),(3),(3),(3),(4)
                    insert into #mainTable values (1,5),(2,5),(3,5),(4,5)

                    select value,count(*) as AddValue
                    into #otherTemp
                    from #temp t
                    group by value

                    update m
                    set mainValue = m.mainValue+ ot.AddValue
                    from #otherTemp ot
                    inner join #mainTable m on m.id=ot.value

                    select * from #mainTable






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 14 '18 at 18:26









                    Eray BalkanliEray Balkanli

                    4,18942044




                    4,18942044























                        0














                        This is a little tricky, but you can do it by aggregating first:



                        update table t join
                        (select bar, count(*) as factor
                        from (select 1 as bar union all select 3 as bar union all select 3 as bar union all select 3 as bar union all select 5
                        ) b
                        ) b
                        on t.bar = b.bar
                        t.foo = t.foo - bar.factor;





                        share|improve this answer




























                          0














                          This is a little tricky, but you can do it by aggregating first:



                          update table t join
                          (select bar, count(*) as factor
                          from (select 1 as bar union all select 3 as bar union all select 3 as bar union all select 3 as bar union all select 5
                          ) b
                          ) b
                          on t.bar = b.bar
                          t.foo = t.foo - bar.factor;





                          share|improve this answer


























                            0












                            0








                            0







                            This is a little tricky, but you can do it by aggregating first:



                            update table t join
                            (select bar, count(*) as factor
                            from (select 1 as bar union all select 3 as bar union all select 3 as bar union all select 3 as bar union all select 5
                            ) b
                            ) b
                            on t.bar = b.bar
                            t.foo = t.foo - bar.factor;





                            share|improve this answer













                            This is a little tricky, but you can do it by aggregating first:



                            update table t join
                            (select bar, count(*) as factor
                            from (select 1 as bar union all select 3 as bar union all select 3 as bar union all select 3 as bar union all select 5
                            ) b
                            ) b
                            on t.bar = b.bar
                            t.foo = t.foo - bar.factor;






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 14 '18 at 19:24









                            Gordon LinoffGordon Linoff

                            765k35296400




                            765k35296400






























                                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%2f53306361%2fenabling-duplicates-in-where-in%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







                                這個網誌中的熱門文章

                                Xamarin.form Move up view when keyboard appear

                                Post-Redirect-Get with Spring WebFlux and Thymeleaf

                                Anylogic : not able to use stopDelay()