Solución:
Si no desea (explícitamente) usar tablas temporales, esto funcionará:
SELECT id FROM (
(SELECT 1 AS id) UNION ALL
(SELECT 2 AS id) UNION ALL
(SELECT 3 AS id) UNION ALL
(SELECT 4 AS id) UNION ALL
(SELECT 5 AS id)
) AS list
LEFT JOIN users USING (id)
WHERE users.id IS NULL
Sin embargo, es bastante feo, bastante largo y tengo dudas sobre cómo funcionaría si la lista de ID es larga.
Dados los números son una lista fija. La forma más rápida en la que puedo pensar es tener una tabla de prueba, poblada con esos números y hacer
instrucción select no probada, pero seguirá el princpal.
select test.number
from test
left join
users
on
test.number = users.id
where test.number <> users.id
Luego, obtendrá todos los números que no tienen un ID de usuario coincidente y, por lo tanto, podrá completar los huecos.
Tenía la misma necesidad y se basó en la respuesta de BugFinder usando una tabla temporal en la sesión. De esta manera, se destruirá automáticamente después de que termine con la consulta, por lo que no tengo que ocuparme de la limpieza de la casa, ya que ejecutaré este tipo de consulta con frecuencia.
Crea la tabla temporal:
CREATE TEMPORARY TABLE tmp_table (id INT UNSIGNED);
Complete tmp_table con los valores que comprobará:
INSERT INTO tmp_table (id) values (1),(2),(3),(4),(5);
Con la tabla creada y poblada, ejecute la consulta como con cualquier tabla normal:
SELECT tmp_table.id
FROM tmp_table
LEFT JOIN users u
ON tmp_table.id = u.id
WHERE u.id IS NULL;
Esta información sobre las tablas temporales de MySQL también fue útil