¿Cómo puedo hacer una instrucción SQL que busca registros no asociados?
-
21-09-2019 - |
Pregunta
Tengo dos tablas de la siguiente manera:
tblCountry (countryID, countryCode)
tblProjectCountry(ProjectID, countryID)
La tabla tblCountry
es una lista de todos los países con sus códigos y los asociados de mesa tblProjectCountry
ciertos países con determinados proyectos. Necesito una sentencia SQL que me da una lista de los países con su código de país que no tienen asociado un registro en la tabla tblProjectCountry
. hasta el momento que llegué a aquí:
SELECT tblCountry.countryID, tblCountry.countryCode
FROM tblProjectCountry INNER JOIN
tblCountry ON tblProjectCountry.countryID = tblCountry.countryID
WHERE (SELECT COUNT(ProjectID)
FROM tblProjectCountry
WHERE (ProjectID = 1) AND (countryID = tblCountry.countryID)) = 0
La declaración anterior analiza como correcta, pero no dan el resultado exacto que estoy buscando. ¿Alguien puede ayudar?
Solución
¿Esto funciona?
SELECT countryID, countryCode
FROM tblCountry
WHERE countryID NOT IN ( SELECT countryID FROM tblProjectCountry )
Otros consejos
Otra alternativa:
SELECT outerTbl.countryID, outerTbl.countryCode
FROM tblCountry AS outerTbl
WHERE NOT EXISTS
(
SELECT countryID FROM tblProjectCountry WHERE countryID = outerTbl.countryID
)
Esta utiliza lo que se llama un subconsulta correlacionada
Tenga en cuenta que también hacen uso de la EXISTE palabra clave ( véase también )
En SQL Server, NO existe es generalmente piensa que es más performante . Por otra RDMS su kilometraje puede variar .
Hay, al menos, dos maneras de encontrar los registros no asociados.
1. Usando LEFT JOIN
SELECT DISTINCT -- each country only once
tblCountry.countryID,
tblCountry.tblCountry
FROM
tblCountry
LEFT JOIN
tblProjectCountry
ON
tblProjectCountry.countryID = tblCountry.countryID
WHERE
tblProjectCountry.ProjectID IS NULL -- get only records with no pair in projects table
ORDER BY
tblCountry.countryID
erikkallen mencionado esto podría no realizar bien .
2. Usando NOT EXISTS
Varios versión de utilizar NOT EXISTS
o IN
fueron sugeridas por rohancragg y otros:
SELECT
tblCountry.countryID,
tblCountry.tblCountry
FROM
tblCountry
WHERE
-- get only records with no pair in projects table
NOT EXISTS (SELECT TOP 1 1 FROM tblProjectCountry WHERE tblProjectCountry.countryID = tblCountry.countryID)
ORDER BY
tblCountry.countryID
depende de su DBMS y tamaño de los países y los proyectos de tablas de ambos versión podría obtener mejores resultados.
En mi prueba en MS SQL 2005 no hubo una diferencia significativa entre la primera y la segunda consulta de mesa con ~ 250 países y ~ 5000 proyectos . Sin embargo en la mesa con más de 3M proyectos segunda versión (usando NOT EXISTS
) realizado mucho, mucho mejor.
Así que, como siempre, vale la pena comprobar ambas versiones.
SELECT ... DONDE ID NO IN (SELECT ...)