3

i Know this question asked several times in StackOverFlow. i have tried few of them but i am out of luck.

i have a MySQL table where there is a field(orders_id) which is might appear randomly in the table (Not sequentially) and i need to find out which ids are missing from the table.


 orders_id     product_name       qty    
       1007      Wireless Mouse      1
       1000      Laptop              1
       1004      Wireless Mouse      3
       1020      PC                  3
       1003      Wireless Mouse      4
       1025      IPAD                4
       1026      iphone              1

Expected Answer:

Assume orders_id start from 1000.

  orders_id     
       1000 
       1001
       1002     
       1005      
       1006    
       1008      
      ......  


i have already created above table at "SqlFiddle" , you guys can use it.

See table: SQLfiddle

**the SQL i have tried: **

declare @id int
declare @maxid int

set @id = 1
select @maxid = max(`orders_id`) from orders

create temporary table IDSeq
(
    id int
)

while @id < @maxid
begin
    insert into IDSeq values(@id)

    set @id = @id + 1
end

select 
    s.id 
from 
    idseq s 
    left join orders t on 
        s.id = t.`orders_id` 
 where t.`orders_id` is null

 drop table IDSeq

I have taken above SQL from the following Answer:

SQL: find missing IDs in a table

i have also tried the ANSI SQL:

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

Anyone has any idea?? how can i find out the missing orders id.

Community
  • 1
  • 1
Anam
  • 11,999
  • 9
  • 49
  • 63
  • In what way did the "SQL I tried" fail? That looks like a reasonable solution, assuming your `order_id` is also an integer. If that did not work, describe what happened. – BellevueBob Nov 11 '12 at 01:41
  • Order_id is "varchar" in original table nut i can convert to INT, problem is at "declare @id int" i have getting the following errors. – Anam Nov 11 '12 at 01:50
  • [Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'declare @id int declare @maxid int set @id = 1 select @maxid = max(`zencart' at line 1 – Anam Nov 11 '12 at 01:50

1 Answers1

4

Here is another solution to do this:

CREATE TABLE TEMP 
(n int);
INSERT INTO Temp VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

SET @maxid = (SELECT MAX(orders_id) FROM orders);

SELECT     s.id 
FROM
(
    SELECT id
    FROM
    (
       SELECT t4.n * 1000 + t3.n * 100 + t2.n * 10 + t1.n + 1 AS id
       FROM         TEMP AS t1
       CROSS JOIN TEMP AS t2
       CROSS JOIN TEMP AS t3
       CROSS JOIN TEMP AS t4
    ) t 
    WHERE id BETWEEN 1000 AND @maxid
) s 
LEFT JOIN orders t ON s.id = t.`orders_id` 
WHERE t.`orders_id` IS NULL;

This should give you the orders_ids:

ID
1001
1002
1005
1006
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1021
1022
1023
1024

SQL Fiddle Demo

Note that: I created a TEMP table with values from 0 to 9, in order to use to generate an anchor table containing values from 1 to 10000 instead of the while loop that you had in the query you posted. You can control the values from this table depending on the values in your table. If you had values that exceed 10000 CROSS JOIN the TEMP table one more time.

Update: If the orders_id is of datatype varchar just cast it to INTEGER like so:

SELECT     s.id 
FROM
(
    SELECT id
    FROM
    (
       SELECT t4.n * 1000 + t3.n * 100 + t2.n * 10 + t1.n + 1 AS id
       FROM         TEMP AS t1
       CROSS JOIN TEMP AS t2
       CROSS JOIN TEMP AS t3
       CROSS JOIN TEMP AS t4
  ) t WHERE id between 1000 AND @maxid
) s 
LEFT JOIN
(
    SELECT CONVERT(orders_id, UNSIGNED INTEGER) AS orders_id 
    FROM orders
) t ON s.id = t.`orders_id` 
WHERE t.`orders_id` IS NULL;

Updated SQL Fiddle Demo

Mahmoud Gamal
  • 78,257
  • 17
  • 139
  • 164
  • @Enam - Cast it to integer with `CONVERT(orders_id, UNSIGNED INTEGER) AS orders_id` or like so. See my edit – Mahmoud Gamal Nov 11 '12 at 02:12
  • one more things...can i use temporary table instead of table...CREATE temporary TABLE TEMP (n int); INSERT INTO Temp VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);.. – Anam Nov 11 '12 at 02:31
  • @enam - You can use a temporary table like what your did in your question. – Mahmoud Gamal Nov 11 '12 at 02:42