El síntoma: la consulta exterior esperaba un valor, pero la subconsulta devuelve una fila con varias columnas
Una subconsulta puede devolver muchas filas, muchas columnas o ambas cosas. El error de esta guía aparece cuando el contexto exterior necesita un valor escalar —por ejemplo, a la derecha de =— y la consulta interior selecciona dos o más columnas.
PostgreSQL define una subconsulta escalar como una consulta que devuelve exactamente una fila y una columna. MySQL muestra el error 1241 (21000): Operand should contain 1 column(s) en este tipo de uso. SQL Server documenta que una subconsulta introducida por un operador de comparación solo puede incluir una expresión o nombre de columna en su lista de selección. SQLite también distingue una subconsulta de una columna, que es escalar, de una subconsulta de varias columnas, que representa un valor de fila y solo puede utilizarse en contextos compatibles.
Ejemplo reproducible: una fila correcta, pero dos columnas de más
La subconsulta siguiente encuentra exactamente al cliente 1. El problema no es el número de filas: es que devuelve ciudad y activo cuando la expresión exterior solo está comparando ciudad.
WITH clientes(id, nombre, ciudad, activo) AS (
VALUES (1, 'Ana', 'Madrid', 1),
(2, 'Luis', 'Madrid', 1),
(3, 'Marta', 'Sevilla', 1),
(4, 'Pablo', 'Madrid', 0)
)
SELECT id, nombre
FROM clientes
WHERE ciudad = (
SELECT ciudad, activo
FROM clientes
WHERE id = 1
);En una prueba local con SQLite esta forma falla con row value misused. En PostgreSQL y MySQL el diagnóstico equivalente señala que la subconsulta utilizada como valor no puede devolver más de una columna.
Corrección 1: selecciona solo la columna que necesita la comparación
Si la pregunta es «¿qué clientes viven en la misma ciudad que el cliente 1?», la subconsulta debe devolver únicamente ciudad.
WITH clientes(id, nombre, ciudad, activo) AS (
VALUES (1, 'Ana', 'Madrid', 1),
(2, 'Luis', 'Madrid', 1),
(3, 'Marta', 'Sevilla', 1),
(4, 'Pablo', 'Madrid', 0)
)
SELECT id, nombre
FROM clientes
WHERE ciudad = (
SELECT ciudad
FROM clientes
WHERE id = 1
)
ORDER BY id;| id | nombre |
|---|---|
| 1 | Ana |
| 2 | Luis |
| 4 | Pablo |
Corrección 2: si de verdad necesitas comparar varias columnas, expresa esa intención
A veces las dos columnas sí forman parte de la pregunta. Por ejemplo: «¿qué clientes tienen la misma ciudad y el mismo estado activo que el cliente 1?». En vez de intentar convertir dos columnas en un escalar, una opción portable y clara es correlacionarlas mediante EXISTS.
WITH clientes(id, nombre, ciudad, activo) AS (
VALUES (1, 'Ana', 'Madrid', 1),
(2, 'Luis', 'Madrid', 1),
(3, 'Marta', 'Sevilla', 1),
(4, 'Pablo', 'Madrid', 0)
)
SELECT c.id, c.nombre
FROM clientes AS c
WHERE EXISTS (
SELECT 1
FROM clientes AS ref
WHERE ref.id = 1
AND ref.ciudad = c.ciudad
AND ref.activo = c.activo
)
ORDER BY c.id;| id | nombre |
|---|---|
| 1 | Ana |
| 2 | Luis |
Algunos motores admiten comparaciones de valores de fila. PostgreSQL, MySQL y SQLite tienen sintaxis para comparar tuplas o filas en determinados contextos. No la confundas con una subconsulta escalar: si escribes un valor escalar a la izquierda, la subconsulta de la derecha también debe tener forma escalar.
EXISTS es una excepción importante
EXISTS no consume los valores seleccionados: solo comprueba si la subconsulta devuelve alguna fila. Por eso puede verse SELECT * o una lista de columnas dentro de EXISTS sin que eso signifique que una subconsulta escalar acepte varias columnas. La pregunta es distinta: existencia de filas, no obtención de un valor.
Método de diagnóstico
- Ejecuta la subconsulta sola. Anota cuántas filas y cuántas columnas devuelve.
- Identifica la forma que exige el contexto. Una comparación escalar necesita un valor;
EXISTSnecesita saber si hay filas; una comparación de fila necesita componentes compatibles a ambos lados. - Elimina columnas decorativas. No selecciones un
id, nombre o estado adicional solo porque resulte útil para inspeccionar el dato. - Separa el diagnóstico de la solución. Puedes ejecutar temporalmente varias columnas para depurar, pero la subconsulta final debe devolver la forma que la expresión exterior consume.
Error frecuente: confundir “más de una columna” con “más de una fila”
Son dos problemas de cardinalidad diferentes
Una subconsulta puede devolver una fila con dos columnas o dos filas con una sola columna. El primer caso se corrige ajustando la anchura del resultado o usando un contexto de fila; el segundo exige revisar cuántos registros puede producir y si necesitas IN, EXISTS o un valor realmente único. No uses LIMIT 1 para un problema de columnas: limitar filas no elimina columnas.
Práctica correctiva
Decide si necesitas una columna o dos condiciones
Con la misma tabla clientes, quieres devolver únicamente los clientes que comparten ciudad y estado activo con el cliente 1. Una subconsulta como ciudad = (SELECT ciudad, activo ...) falla. Reescribe la consulta sin perder ninguna de las dos condiciones.
EXISTS permite expresar ambas igualdades dentro de la subconsulta.Solución razonada
Correlaciona la fila exterior con el cliente de referencia mediante las dos columnas. Así la subconsulta responde «¿existe la fila de referencia con estos mismos atributos?» y no intenta devolver dos valores dentro de una expresión escalar.
SELECT c.id, c.nombre
FROM clientes AS c
WHERE EXISTS (
SELECT 1
FROM clientes AS ref
WHERE ref.id = 1
AND ref.ciudad = c.ciudad
AND ref.activo = c.activo
)
ORDER BY c.id;Con los datos del ejemplo devuelve Ana y Luis. Pablo comparte ciudad, pero no el estado activo.
Qué debes recordar
- Una subconsulta escalar devuelve una sola columna.
- Una fila con dos columnas no es lo mismo que dos filas con una columna.
- Selecciona únicamente el dato que la expresión exterior necesita.
- Si debes relacionar varios atributos, usa una forma que exprese esa relación, como
EXISTScon condiciones explícitas. EXISTSes diferente: comprueba filas y no utiliza los valores de su listaSELECT.