sql >> Base de Datos >  >> RDS >> Sqlserver

La consulta SQL IN produce un resultado extraño

Este comportamiento, aunque poco intuitivo, está muy bien definido en la base de conocimiento de Microsoft:

KB #298674:PRB:la subconsulta resuelve nombres de columna en tablas externas

De ese artículo:

CREATE TABLE X1 (ColA INT, ColB INT)
CREATE TABLE X2 (ColC INT, ColD INT)
SELECT ColA FROM X1 WHERE ColA IN (Select ColB FROM X2)
SELECT ColA FROM X1 WHERE ColA in (Select X2.ColB FROM X2)

La gente se ha estado quejando de este problema durante años, pero Microsoft no lo va a solucionar. Después de todo, cumple con el estándar, que esencialmente establece:

Más información en los siguientes "errores" de Connect junto con múltiples confirmaciones oficiales de que este comportamiento es por diseño y no va a cambiar (por lo que tendrá que cambiar el suyo, es decir, usar siempre alias ):

Conexión n.° 338468:la resolución del nombre de la columna CTE en la subconsulta no está validada
Connect #735178:la subconsulta T-SQL no funciona en algunos casos cuando se usa el operador IN
Conectar #302281:la columna inexistente hace que se ignore la subconsulta
Conectar #772612:Error de alias que no se informa dentro de un operador IN
Conectar #265772:Error usando sub seleccionar

En su caso, es probable que este "error" ocurra mucho menos si usa nombres más significativos que ID, OID y PID. Hace Order.PID apunta a Person.id o Person.PID ? Diseñe sus tablas para que las personas puedan descubrir las relaciones sin tener que preguntarle. Un PersonID siempre debe ser un PersonID , sin importar en qué parte del esquema se encuentre; lo mismo con un OrderID . Guardar algunos caracteres de escritura no es un buen precio a pagar por un esquema completamente ambiguo.

Podrías escribir un EXISTS cláusula en su lugar:

... FROM dbo.Person AS p WHERE EXISTS 
(
  SELECT 1 FROM dbo.[Order] AS o
  WHERE o.PID = p.id -- or is it PID? See why it pays to be explicit?
);