MySQL get missing IDs from table












27















I have this table in MySQL, for example:



ID | Name
1 | Bob
4 | Adam
6 | Someguy


If you notice, there is no ID number (2, 3 and 5).



How can I write a query so that MySQL would answer the missing IDs only, in this case: "2,3,5" ?










share|improve this question



























    27















    I have this table in MySQL, for example:



    ID | Name
    1 | Bob
    4 | Adam
    6 | Someguy


    If you notice, there is no ID number (2, 3 and 5).



    How can I write a query so that MySQL would answer the missing IDs only, in this case: "2,3,5" ?










    share|improve this question

























      27












      27








      27


      18






      I have this table in MySQL, for example:



      ID | Name
      1 | Bob
      4 | Adam
      6 | Someguy


      If you notice, there is no ID number (2, 3 and 5).



      How can I write a query so that MySQL would answer the missing IDs only, in this case: "2,3,5" ?










      share|improve this question














      I have this table in MySQL, for example:



      ID | Name
      1 | Bob
      4 | Adam
      6 | Someguy


      If you notice, there is no ID number (2, 3 and 5).



      How can I write a query so that MySQL would answer the missing IDs only, in this case: "2,3,5" ?







      mysql






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Sep 7 '12 at 20:44









      ReacenReacen

      88441430




      88441430
























          6 Answers
          6






          active

          oldest

          votes


















          23














          SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
          FROM testtable AS a, testtable AS b
          WHERE a.id < b.id
          GROUP BY a.id
          HAVING start < MIN(b.id)


          Hope this link also helps
          http://www.codediesel.com/mysql/sequence-gaps-in-mysql/






          share|improve this answer



















          • 2





            working fine :) , but very slow on big data :(

            – iiic
            May 13 '16 at 12:17











          • This was genius! Thanks

            – McRui
            May 20 '18 at 19:32



















          19














          A more efficent query:



          SELECT (t1.id + 1) as gap_starts_at, 
          (SELECT MIN(t3.id) -1 FROM my_table t3 WHERE t3.id > t1.id) as gap_ends_at
          FROM my_table t1
          WHERE NOT EXISTS (SELECT t2.id FROM my_table t2 WHERE t2.id = t1.id + 1)
          HAVING gap_ends_at IS NOT NULL





          share|improve this answer


























          • Thanks Ivan. This runs so much quicker!

            – MikeC
            May 19 '16 at 1:24













          • This worked for me, except that it missed the initial gap starting at id=1

            – egprentice
            Oct 4 '17 at 14:56



















          3














          To add a little to Ivan's answer, this version shows numbers missing at the beginning if 1 doesn't exist:



          SELECT 1 as gap_starts_at,
          (SELECT MIN(t4.id) -1 FROM testtable t4 WHERE t4.id > 1) as gap_ends_at
          FROM testtable t5
          WHERE NOT EXISTS (SELECT t6.id FROM testtable t6 WHERE t6.id = 1)
          HAVING gap_ends_at IS NOT NULL limit 1
          UNION
          SELECT (t1.id + 1) as gap_starts_at,
          (SELECT MIN(t3.id) -1 FROM testtable t3 WHERE t3.id > t1.id) as gap_ends_at
          FROM testtable t1
          WHERE NOT EXISTS (SELECT t2.id FROM testtable t2 WHERE t2.id = t1.id + 1)
          HAVING gap_ends_at IS NOT NULL;





          share|improve this answer


























          • Impressive.. great use of union and range

            – Clain Dsilva
            Apr 25 '18 at 9:20



















          2














          Above queries will give two columns so you can try this to get the missing numbers in a single column



          select start from 
          (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
          FROM sequence AS a, sequence AS b
          WHERE a.id < b.id
          GROUP BY a.id
          HAVING start < MIN(b.id)) b
          UNION
          select c.end from (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
          FROM sequence AS a, sequence AS b
          WHERE a.id < b.id
          GROUP BY a.id
          HAVING start < MIN(b.id)) c order by start;





          share|improve this answer


























          • With this one-column version, I get (for example) 475, 477, 506, 508, 513 but with the two-column version, it gets me the [475,475], [477,506], [508,513] which tells me I am missing numbers 475, 477-506, and 508-513.

            – Jo.
            Jun 30 '17 at 20:04



















          0














          It would be far more efficient to get the start of the gap in one query and the end of the gap in one query.



          I had 18M records and it took me less than a second each to get the two results. When I tried getting them together my query timed out after an hour.



          Get the start of gap:



          SELECT (t1.id + 1) as MissingID
          FROM sequence t1
          WHERE NOT EXISTS
          (SELECT t2.id
          FROM sequence t2
          WHERE t2.id = t1.id + 1);


          Get the end of gap:



          SELECT (t1.id - 1) as MissingID
          FROM sequence t1
          WHERE NOT EXISTS
          (SELECT t2.id
          FROM sequence t2
          WHERE t2.id = t1.id - 1);





          share|improve this answer





















          • 1





            Just a clarrification, I was suppose to have 18m records. It turns out I had only 3m records in my database and missed 15m records.

            – James G
            Nov 23 '18 at 1:09



















          0














          Rather than returning multiple ranges of IDs, if you instead want to retrieve every single missing ID itself, each one on its own row, you could do the following:



          SELECT id+1 FROM table WHERE id NOT IN (SELECT id-1 FROM table) ORDER BY 1


          The query is very efficient. However, it also includes one extra row on the end, which is equal to the highest ID number, plus 1. This last row can be ignored in your server script, by checking for the number of rows returned (mysqli_num_rows), and then using a for loop if the number of rows is greater than 1 (the query will always return at least one row).






          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%2f12325132%2fmysql-get-missing-ids-from-table%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            6 Answers
            6






            active

            oldest

            votes








            6 Answers
            6






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            23














            SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM testtable AS a, testtable AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)


            Hope this link also helps
            http://www.codediesel.com/mysql/sequence-gaps-in-mysql/






            share|improve this answer



















            • 2





              working fine :) , but very slow on big data :(

              – iiic
              May 13 '16 at 12:17











            • This was genius! Thanks

              – McRui
              May 20 '18 at 19:32
















            23














            SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM testtable AS a, testtable AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)


            Hope this link also helps
            http://www.codediesel.com/mysql/sequence-gaps-in-mysql/






            share|improve this answer



















            • 2





              working fine :) , but very slow on big data :(

              – iiic
              May 13 '16 at 12:17











            • This was genius! Thanks

              – McRui
              May 20 '18 at 19:32














            23












            23








            23







            SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM testtable AS a, testtable AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)


            Hope this link also helps
            http://www.codediesel.com/mysql/sequence-gaps-in-mysql/






            share|improve this answer













            SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM testtable AS a, testtable AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)


            Hope this link also helps
            http://www.codediesel.com/mysql/sequence-gaps-in-mysql/







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Sep 7 '12 at 20:50









            hagensofthagensoft

            1,139813




            1,139813








            • 2





              working fine :) , but very slow on big data :(

              – iiic
              May 13 '16 at 12:17











            • This was genius! Thanks

              – McRui
              May 20 '18 at 19:32














            • 2





              working fine :) , but very slow on big data :(

              – iiic
              May 13 '16 at 12:17











            • This was genius! Thanks

              – McRui
              May 20 '18 at 19:32








            2




            2





            working fine :) , but very slow on big data :(

            – iiic
            May 13 '16 at 12:17





            working fine :) , but very slow on big data :(

            – iiic
            May 13 '16 at 12:17













            This was genius! Thanks

            – McRui
            May 20 '18 at 19:32





            This was genius! Thanks

            – McRui
            May 20 '18 at 19:32













            19














            A more efficent query:



            SELECT (t1.id + 1) as gap_starts_at, 
            (SELECT MIN(t3.id) -1 FROM my_table t3 WHERE t3.id > t1.id) as gap_ends_at
            FROM my_table t1
            WHERE NOT EXISTS (SELECT t2.id FROM my_table t2 WHERE t2.id = t1.id + 1)
            HAVING gap_ends_at IS NOT NULL





            share|improve this answer


























            • Thanks Ivan. This runs so much quicker!

              – MikeC
              May 19 '16 at 1:24













            • This worked for me, except that it missed the initial gap starting at id=1

              – egprentice
              Oct 4 '17 at 14:56
















            19














            A more efficent query:



            SELECT (t1.id + 1) as gap_starts_at, 
            (SELECT MIN(t3.id) -1 FROM my_table t3 WHERE t3.id > t1.id) as gap_ends_at
            FROM my_table t1
            WHERE NOT EXISTS (SELECT t2.id FROM my_table t2 WHERE t2.id = t1.id + 1)
            HAVING gap_ends_at IS NOT NULL





            share|improve this answer


























            • Thanks Ivan. This runs so much quicker!

              – MikeC
              May 19 '16 at 1:24













            • This worked for me, except that it missed the initial gap starting at id=1

              – egprentice
              Oct 4 '17 at 14:56














            19












            19








            19







            A more efficent query:



            SELECT (t1.id + 1) as gap_starts_at, 
            (SELECT MIN(t3.id) -1 FROM my_table t3 WHERE t3.id > t1.id) as gap_ends_at
            FROM my_table t1
            WHERE NOT EXISTS (SELECT t2.id FROM my_table t2 WHERE t2.id = t1.id + 1)
            HAVING gap_ends_at IS NOT NULL





            share|improve this answer















            A more efficent query:



            SELECT (t1.id + 1) as gap_starts_at, 
            (SELECT MIN(t3.id) -1 FROM my_table t3 WHERE t3.id > t1.id) as gap_ends_at
            FROM my_table t1
            WHERE NOT EXISTS (SELECT t2.id FROM my_table t2 WHERE t2.id = t1.id + 1)
            HAVING gap_ends_at IS NOT NULL






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Feb 2 '18 at 13:11

























            answered Dec 17 '14 at 7:45









            Iván PérezIván Pérez

            1,10011035




            1,10011035













            • Thanks Ivan. This runs so much quicker!

              – MikeC
              May 19 '16 at 1:24













            • This worked for me, except that it missed the initial gap starting at id=1

              – egprentice
              Oct 4 '17 at 14:56



















            • Thanks Ivan. This runs so much quicker!

              – MikeC
              May 19 '16 at 1:24













            • This worked for me, except that it missed the initial gap starting at id=1

              – egprentice
              Oct 4 '17 at 14:56

















            Thanks Ivan. This runs so much quicker!

            – MikeC
            May 19 '16 at 1:24







            Thanks Ivan. This runs so much quicker!

            – MikeC
            May 19 '16 at 1:24















            This worked for me, except that it missed the initial gap starting at id=1

            – egprentice
            Oct 4 '17 at 14:56





            This worked for me, except that it missed the initial gap starting at id=1

            – egprentice
            Oct 4 '17 at 14:56











            3














            To add a little to Ivan's answer, this version shows numbers missing at the beginning if 1 doesn't exist:



            SELECT 1 as gap_starts_at,
            (SELECT MIN(t4.id) -1 FROM testtable t4 WHERE t4.id > 1) as gap_ends_at
            FROM testtable t5
            WHERE NOT EXISTS (SELECT t6.id FROM testtable t6 WHERE t6.id = 1)
            HAVING gap_ends_at IS NOT NULL limit 1
            UNION
            SELECT (t1.id + 1) as gap_starts_at,
            (SELECT MIN(t3.id) -1 FROM testtable t3 WHERE t3.id > t1.id) as gap_ends_at
            FROM testtable t1
            WHERE NOT EXISTS (SELECT t2.id FROM testtable t2 WHERE t2.id = t1.id + 1)
            HAVING gap_ends_at IS NOT NULL;





            share|improve this answer


























            • Impressive.. great use of union and range

              – Clain Dsilva
              Apr 25 '18 at 9:20
















            3














            To add a little to Ivan's answer, this version shows numbers missing at the beginning if 1 doesn't exist:



            SELECT 1 as gap_starts_at,
            (SELECT MIN(t4.id) -1 FROM testtable t4 WHERE t4.id > 1) as gap_ends_at
            FROM testtable t5
            WHERE NOT EXISTS (SELECT t6.id FROM testtable t6 WHERE t6.id = 1)
            HAVING gap_ends_at IS NOT NULL limit 1
            UNION
            SELECT (t1.id + 1) as gap_starts_at,
            (SELECT MIN(t3.id) -1 FROM testtable t3 WHERE t3.id > t1.id) as gap_ends_at
            FROM testtable t1
            WHERE NOT EXISTS (SELECT t2.id FROM testtable t2 WHERE t2.id = t1.id + 1)
            HAVING gap_ends_at IS NOT NULL;





            share|improve this answer


























            • Impressive.. great use of union and range

              – Clain Dsilva
              Apr 25 '18 at 9:20














            3












            3








            3







            To add a little to Ivan's answer, this version shows numbers missing at the beginning if 1 doesn't exist:



            SELECT 1 as gap_starts_at,
            (SELECT MIN(t4.id) -1 FROM testtable t4 WHERE t4.id > 1) as gap_ends_at
            FROM testtable t5
            WHERE NOT EXISTS (SELECT t6.id FROM testtable t6 WHERE t6.id = 1)
            HAVING gap_ends_at IS NOT NULL limit 1
            UNION
            SELECT (t1.id + 1) as gap_starts_at,
            (SELECT MIN(t3.id) -1 FROM testtable t3 WHERE t3.id > t1.id) as gap_ends_at
            FROM testtable t1
            WHERE NOT EXISTS (SELECT t2.id FROM testtable t2 WHERE t2.id = t1.id + 1)
            HAVING gap_ends_at IS NOT NULL;





            share|improve this answer















            To add a little to Ivan's answer, this version shows numbers missing at the beginning if 1 doesn't exist:



            SELECT 1 as gap_starts_at,
            (SELECT MIN(t4.id) -1 FROM testtable t4 WHERE t4.id > 1) as gap_ends_at
            FROM testtable t5
            WHERE NOT EXISTS (SELECT t6.id FROM testtable t6 WHERE t6.id = 1)
            HAVING gap_ends_at IS NOT NULL limit 1
            UNION
            SELECT (t1.id + 1) as gap_starts_at,
            (SELECT MIN(t3.id) -1 FROM testtable t3 WHERE t3.id > t1.id) as gap_ends_at
            FROM testtable t1
            WHERE NOT EXISTS (SELECT t2.id FROM testtable t2 WHERE t2.id = t1.id + 1)
            HAVING gap_ends_at IS NOT NULL;






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jun 30 '17 at 20:16

























            answered Jun 30 '17 at 20:10









            Jo.Jo.

            62611116




            62611116













            • Impressive.. great use of union and range

              – Clain Dsilva
              Apr 25 '18 at 9:20



















            • Impressive.. great use of union and range

              – Clain Dsilva
              Apr 25 '18 at 9:20

















            Impressive.. great use of union and range

            – Clain Dsilva
            Apr 25 '18 at 9:20





            Impressive.. great use of union and range

            – Clain Dsilva
            Apr 25 '18 at 9:20











            2














            Above queries will give two columns so you can try this to get the missing numbers in a single column



            select start from 
            (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM sequence AS a, sequence AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)) b
            UNION
            select c.end from (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM sequence AS a, sequence AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)) c order by start;





            share|improve this answer


























            • With this one-column version, I get (for example) 475, 477, 506, 508, 513 but with the two-column version, it gets me the [475,475], [477,506], [508,513] which tells me I am missing numbers 475, 477-506, and 508-513.

              – Jo.
              Jun 30 '17 at 20:04
















            2














            Above queries will give two columns so you can try this to get the missing numbers in a single column



            select start from 
            (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM sequence AS a, sequence AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)) b
            UNION
            select c.end from (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM sequence AS a, sequence AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)) c order by start;





            share|improve this answer


























            • With this one-column version, I get (for example) 475, 477, 506, 508, 513 but with the two-column version, it gets me the [475,475], [477,506], [508,513] which tells me I am missing numbers 475, 477-506, and 508-513.

              – Jo.
              Jun 30 '17 at 20:04














            2












            2








            2







            Above queries will give two columns so you can try this to get the missing numbers in a single column



            select start from 
            (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM sequence AS a, sequence AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)) b
            UNION
            select c.end from (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM sequence AS a, sequence AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)) c order by start;





            share|improve this answer















            Above queries will give two columns so you can try this to get the missing numbers in a single column



            select start from 
            (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM sequence AS a, sequence AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)) b
            UNION
            select c.end from (SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
            FROM sequence AS a, sequence AS b
            WHERE a.id < b.id
            GROUP BY a.id
            HAVING start < MIN(b.id)) c order by start;






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Feb 9 '17 at 8:42









            Ish

            1,629828




            1,629828










            answered Aug 26 '15 at 12:48









            Karan Kumar MahtoKaran Kumar Mahto

            667




            667













            • With this one-column version, I get (for example) 475, 477, 506, 508, 513 but with the two-column version, it gets me the [475,475], [477,506], [508,513] which tells me I am missing numbers 475, 477-506, and 508-513.

              – Jo.
              Jun 30 '17 at 20:04



















            • With this one-column version, I get (for example) 475, 477, 506, 508, 513 but with the two-column version, it gets me the [475,475], [477,506], [508,513] which tells me I am missing numbers 475, 477-506, and 508-513.

              – Jo.
              Jun 30 '17 at 20:04

















            With this one-column version, I get (for example) 475, 477, 506, 508, 513 but with the two-column version, it gets me the [475,475], [477,506], [508,513] which tells me I am missing numbers 475, 477-506, and 508-513.

            – Jo.
            Jun 30 '17 at 20:04





            With this one-column version, I get (for example) 475, 477, 506, 508, 513 but with the two-column version, it gets me the [475,475], [477,506], [508,513] which tells me I am missing numbers 475, 477-506, and 508-513.

            – Jo.
            Jun 30 '17 at 20:04











            0














            It would be far more efficient to get the start of the gap in one query and the end of the gap in one query.



            I had 18M records and it took me less than a second each to get the two results. When I tried getting them together my query timed out after an hour.



            Get the start of gap:



            SELECT (t1.id + 1) as MissingID
            FROM sequence t1
            WHERE NOT EXISTS
            (SELECT t2.id
            FROM sequence t2
            WHERE t2.id = t1.id + 1);


            Get the end of gap:



            SELECT (t1.id - 1) as MissingID
            FROM sequence t1
            WHERE NOT EXISTS
            (SELECT t2.id
            FROM sequence t2
            WHERE t2.id = t1.id - 1);





            share|improve this answer





















            • 1





              Just a clarrification, I was suppose to have 18m records. It turns out I had only 3m records in my database and missed 15m records.

              – James G
              Nov 23 '18 at 1:09
















            0














            It would be far more efficient to get the start of the gap in one query and the end of the gap in one query.



            I had 18M records and it took me less than a second each to get the two results. When I tried getting them together my query timed out after an hour.



            Get the start of gap:



            SELECT (t1.id + 1) as MissingID
            FROM sequence t1
            WHERE NOT EXISTS
            (SELECT t2.id
            FROM sequence t2
            WHERE t2.id = t1.id + 1);


            Get the end of gap:



            SELECT (t1.id - 1) as MissingID
            FROM sequence t1
            WHERE NOT EXISTS
            (SELECT t2.id
            FROM sequence t2
            WHERE t2.id = t1.id - 1);





            share|improve this answer





















            • 1





              Just a clarrification, I was suppose to have 18m records. It turns out I had only 3m records in my database and missed 15m records.

              – James G
              Nov 23 '18 at 1:09














            0












            0








            0







            It would be far more efficient to get the start of the gap in one query and the end of the gap in one query.



            I had 18M records and it took me less than a second each to get the two results. When I tried getting them together my query timed out after an hour.



            Get the start of gap:



            SELECT (t1.id + 1) as MissingID
            FROM sequence t1
            WHERE NOT EXISTS
            (SELECT t2.id
            FROM sequence t2
            WHERE t2.id = t1.id + 1);


            Get the end of gap:



            SELECT (t1.id - 1) as MissingID
            FROM sequence t1
            WHERE NOT EXISTS
            (SELECT t2.id
            FROM sequence t2
            WHERE t2.id = t1.id - 1);





            share|improve this answer















            It would be far more efficient to get the start of the gap in one query and the end of the gap in one query.



            I had 18M records and it took me less than a second each to get the two results. When I tried getting them together my query timed out after an hour.



            Get the start of gap:



            SELECT (t1.id + 1) as MissingID
            FROM sequence t1
            WHERE NOT EXISTS
            (SELECT t2.id
            FROM sequence t2
            WHERE t2.id = t1.id + 1);


            Get the end of gap:



            SELECT (t1.id - 1) as MissingID
            FROM sequence t1
            WHERE NOT EXISTS
            (SELECT t2.id
            FROM sequence t2
            WHERE t2.id = t1.id - 1);






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 23 '18 at 2:11









            Davіd

            3,66841836




            3,66841836










            answered Nov 23 '18 at 0:50









            James GJames G

            11




            11








            • 1





              Just a clarrification, I was suppose to have 18m records. It turns out I had only 3m records in my database and missed 15m records.

              – James G
              Nov 23 '18 at 1:09














            • 1





              Just a clarrification, I was suppose to have 18m records. It turns out I had only 3m records in my database and missed 15m records.

              – James G
              Nov 23 '18 at 1:09








            1




            1





            Just a clarrification, I was suppose to have 18m records. It turns out I had only 3m records in my database and missed 15m records.

            – James G
            Nov 23 '18 at 1:09





            Just a clarrification, I was suppose to have 18m records. It turns out I had only 3m records in my database and missed 15m records.

            – James G
            Nov 23 '18 at 1:09











            0














            Rather than returning multiple ranges of IDs, if you instead want to retrieve every single missing ID itself, each one on its own row, you could do the following:



            SELECT id+1 FROM table WHERE id NOT IN (SELECT id-1 FROM table) ORDER BY 1


            The query is very efficient. However, it also includes one extra row on the end, which is equal to the highest ID number, plus 1. This last row can be ignored in your server script, by checking for the number of rows returned (mysqli_num_rows), and then using a for loop if the number of rows is greater than 1 (the query will always return at least one row).






            share|improve this answer






























              0














              Rather than returning multiple ranges of IDs, if you instead want to retrieve every single missing ID itself, each one on its own row, you could do the following:



              SELECT id+1 FROM table WHERE id NOT IN (SELECT id-1 FROM table) ORDER BY 1


              The query is very efficient. However, it also includes one extra row on the end, which is equal to the highest ID number, plus 1. This last row can be ignored in your server script, by checking for the number of rows returned (mysqli_num_rows), and then using a for loop if the number of rows is greater than 1 (the query will always return at least one row).






              share|improve this answer




























                0












                0








                0







                Rather than returning multiple ranges of IDs, if you instead want to retrieve every single missing ID itself, each one on its own row, you could do the following:



                SELECT id+1 FROM table WHERE id NOT IN (SELECT id-1 FROM table) ORDER BY 1


                The query is very efficient. However, it also includes one extra row on the end, which is equal to the highest ID number, plus 1. This last row can be ignored in your server script, by checking for the number of rows returned (mysqli_num_rows), and then using a for loop if the number of rows is greater than 1 (the query will always return at least one row).






                share|improve this answer















                Rather than returning multiple ranges of IDs, if you instead want to retrieve every single missing ID itself, each one on its own row, you could do the following:



                SELECT id+1 FROM table WHERE id NOT IN (SELECT id-1 FROM table) ORDER BY 1


                The query is very efficient. However, it also includes one extra row on the end, which is equal to the highest ID number, plus 1. This last row can be ignored in your server script, by checking for the number of rows returned (mysqli_num_rows), and then using a for loop if the number of rows is greater than 1 (the query will always return at least one row).







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Mar 5 at 14:08

























                answered Feb 28 at 8:14









                Tristan BaileyTristan Bailey

                175110




                175110






























                    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%2f12325132%2fmysql-get-missing-ids-from-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

                    "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                    Alcedinidae

                    RAC Tourist Trophy