Return which of the query items are not in the table?

Asked

Viewed 4,048 times

3

Is there any way to return which query items are not in a table?

Let’s say I have an appointment like this:

SELECT id FROM tabela WHERE id IN (1,23,45,68,91,126,345,418,509,610);

This will bring me a table with the records of the query that are present system. But I want to know which of these records were deleted, so I need the items that are not present in the system.

How to resolve this without having to make a query for each record?

You could solve this by creating a temporary table with the searched values and do a LEFT JOIN with the system table searching for NULL in comparison. But it would have some simpler way to return the missing values?

  • 1

    That’s a good question. However, if you are doing this in some programming language (Java, PHP, C#) it would be simpler to retrieve the existing Ids in a vector and make a diff of the result with the original ID vector.

2 answers

4

You could solve this by creating a temporary table with the searched values and do a LEFT JOIN with the system table searching for NULL in comparison. But it would have some simpler way to return the missing values?

In my opinion, the temporary table is the simplest output. An alternative is to use a lot of UNION, but it looks pretty ugly:

SELECT id FROM
   (SELECT 1 AS id UNION SELECT 23 AS id UNION SELECT 45 AS id /* etc */) tbl
WHERE id NOT IN (SELECT id FROM tabela)

Demo in http://sqlfiddle.com/#! 2/812b5/12


You can also use an interesting trick described in this answer of Bacchus to the question How to generate numerical sequences in SQL without creating tables? The idea is to keep an integer table in your bank, with 10 rows (the numbers from 0 to 9):

CREATE TABLE inteiros (i INT);
INSERT INTO inteiros (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);

With this table you can simulate a generator, since Mysql does not support native generators. For example, you can generate numbers from 1 to 1000 like this:

SELECT d3.i*100+d2.i*10+d1.i+1 AS gerador
FROM inteiros AS d1
JOIN inteiros AS d2
JOIN inteiros AS d3;

Applying this to your example, and considering that the ids to be checked are in this range from 0 to 1000, the following query generates the list:

SELECT d3.i*100+d2.i*10+d1.i+1 AS gerador
FROM inteiros AS d1
JOIN inteiros AS d2
JOIN inteiros AS d3
HAVING gerador IN (1,23,45,68,91,126,345,418,509,610);

Finally, using this to get the result you want:

SELECT id FROM (
    SELECT d3.i*100+d2.i*10+d1.i+1 AS id
    FROM inteiros AS d1
    JOIN inteiros AS d2
    JOIN inteiros AS d3
    HAVING gerador IN (1,23,45,68,91,126,345,418,509,610);
) tbl
WHERE id NOT IN (SELECT id FROM tabela)
  • 1

    +1. I was going to suggest the same. SELECT temp.id_nao_encontrado FROM (
 SELECT 10 as id_nao_encontrado FROM DUAL 
 UNION ALL 
 SELECT 20 FROM DUAL 
 UNION ALL 
 SELECT 30 FROM DUAL 
 ) AS temp 
WHERE temp.id_nao_encontrado NOT IN (SELECT id from teste); . For testing: http://sqlfiddle.com/#! 2/812b5/9

  • 2

    Thanks, I took advantage of your schema in my demo. I didn’t know this FROM DUAL, but from what I saw it is optional in Mysql (Selects without FROM are valid).

  • 1

    @bfavaretto As far as I know, FROM DUAL is required only on Oracle.

  • @It’s explained why I didn’t know :)

  • 1

    Yes, only required in oracle (only for documentation): DUAL is purely for the convenience of people who require that all SELECT statements should have FROM and possibly other clauses. MySQL may ignore the clauses. MySQL does not require FROM DUAL if no tables are referenced.

-1

I could use something like that

SELECT id FROM tabela WHERE id NOT IN (1,23,45,68,91,126,345,418,509,610);
  • 4

    It doesn’t work because deleted ids no longer exist in the system. You would need to return the items indicated in the survey that do not find corresponding in the table.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.