Ir al contenido

Joins y subconsultas

Los joins relacionan fuentes SQL y devuelven filas de una consulta. Las relaciones ORM describen asociaciones entre modelos y su carga; son APIs distintas.

Usa alias y nombres calificados para resolver columnas inequívocamente. Una subconsulta acepta un builder, SelectPlan o un callback síncrono que configura un builder nuevo. selectSub, whereExists, whereIn, joinSub y union reutilizan esta normalización. Los planes se incorporan por referencia; termina de configurarlos o clónalos antes de reutilizarlos.

from orionis.support.facades import DB
async def product_categories():
return await (
DB.table("products", alias="p")
.leftJoin("categories", "p.category_id", "=", "c.id", alias="c")
.select("p.id", "p.name")
.selectRaw("c.name", alias="category_name")
.orderBy("p.id")
.get()
)

El ejemplo evita dos columnas name con la misma clave de resultado. Seleccionar columnas homónimas sin alias puede producir claves ambiguas al recuperar diccionarios. Para un modelo que luego guarde cambios o cargue relaciones conserva sus claves necesarias.

La disponibilidad de RIGHT/FULL JOIN depende del servidor. No se emula un JOIN no admitido ni se consulta otro motor automáticamente. Cada terminal mantiene una sola conexión: las subconsultas se compilan en el motor de la consulta exterior, aunque el builder incrustado haya elegido otra conexión.

selectSub(query: Any, alias: str) -> Self

Añade una subconsulta escalar con alias. El motor exige una columna y cardinalidad escalar; el builder no convierte varias filas en una lista.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

from orionis.support.facades import DB
query = DB.table("products").select("id").selectSub(DB.table("products").selectRaw("MAX(price)").toPlan(), "highest_price")

whereExists(query: Any) -> Self

Añade EXISTS con AND. Úsalo para filtrar por la existencia de filas relacionadas sin hidratar modelos.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

from orionis.support.facades import DB
query = DB.table("products", alias="p").whereExists(DB.table("categories", alias="c").select("c.id").whereColumn("c.id", "=", "p.category_id"))

orWhereExists(query: Any) -> Self

Añade EXISTS con OR. Úsalo para filtrar por la existencia de filas relacionadas sin hidratar modelos.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

from orionis.support.facades import DB
query = DB.table("products", alias="p").orWhereExists(DB.table("categories", alias="c").select("c.id").whereColumn("c.id", "=", "p.category_id"))

whereNotExists(query: Any) -> Self

Añade NOT EXISTS con AND. Úsalo para filtrar por la existencia de filas relacionadas sin hidratar modelos.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

from orionis.support.facades import DB
query = DB.table("products", alias="p").whereNotExists(DB.table("categories", alias="c").select("c.id").whereColumn("c.id", "=", "p.category_id"))

orWhereNotExists(query: Any) -> Self

Añade NOT EXISTS con OR. Úsalo para filtrar por la existencia de filas relacionadas sin hidratar modelos.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

from orionis.support.facades import DB
query = DB.table("products", alias="p").orWhereNotExists(DB.table("categories", alias="c").select("c.id").whereColumn("c.id", "=", "p.category_id"))

join(table: str | TableDefinition, first: Any=None, operator: str | None=None, second: str | None=None, *, alias: str | None=None) -> Self

Añade un JOIN INNER. Admite una condición de columnas o un callback JoinClause para combinar condiciones.

ParámetroUso
tableNombre de tabla lógico o TableDefinition. Separa un esquema con un punto y usa alias explícitos en joins.
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Una condición incompleta produce InvalidQueryException. Cada lado del ON debe ser una columna; el soporte del tipo de JOIN depende del motor.

from orionis.support.facades import DB
query = DB.table("products", alias="p").join("categories", "p.category_id", "=", "c.id", alias="c").select("p.id", "c.name")

leftJoin(table: str | TableDefinition, first: Any=None, operator: str | None=None, second: str | None=None, *, alias: str | None=None) -> Self

Añade un JOIN LEFT OUTER. Admite una condición de columnas o un callback JoinClause para combinar condiciones.

ParámetroUso
tableNombre de tabla lógico o TableDefinition. Separa un esquema con un punto y usa alias explícitos en joins.
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Una condición incompleta produce InvalidQueryException. Cada lado del ON debe ser una columna; el soporte del tipo de JOIN depende del motor.

from orionis.support.facades import DB
query = DB.table("products", alias="p").leftJoin("categories", "p.category_id", "=", "c.id", alias="c").select("p.id", "c.name")

rightJoin(table: str | TableDefinition, first: Any=None, operator: str | None=None, second: str | None=None, *, alias: str | None=None) -> Self

Añade un JOIN RIGHT OUTER. Admite una condición de columnas o un callback JoinClause para combinar condiciones.

ParámetroUso
tableNombre de tabla lógico o TableDefinition. Separa un esquema con un punto y usa alias explícitos en joins.
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Una condición incompleta produce InvalidQueryException. Cada lado del ON debe ser una columna; el soporte del tipo de JOIN depende del motor.

from orionis.support.facades import DB
query = DB.table("products", alias="p").rightJoin("categories", "p.category_id", "=", "c.id", alias="c").select("p.id", "c.name")

fullJoin(table: str | TableDefinition, first: Any=None, operator: str | None=None, second: str | None=None, *, alias: str | None=None) -> Self

Añade un JOIN FULL OUTER. Admite una condición de columnas o un callback JoinClause para combinar condiciones.

ParámetroUso
tableNombre de tabla lógico o TableDefinition. Separa un esquema con un punto y usa alias explícitos en joins.
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Una condición incompleta produce InvalidQueryException. Cada lado del ON debe ser una columna; el soporte del tipo de JOIN depende del motor.

from orionis.support.facades import DB
query = DB.table("products", alias="p").fullJoin("categories", "p.category_id", "=", "c.id", alias="c").select("p.id", "c.name")

crossJoin(table: str | TableDefinition, *, alias: str | None=None) -> Self

Añade un producto cartesiano sin condición ON. El número de combinaciones puede crecer como filas_izquierda * filas_derecha.

ParámetroUso
tableNombre de tabla lógico o TableDefinition. Separa un esquema con un punto y usa alias explícitos en joins.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

from orionis.support.facades import DB
query = DB.table("products", alias="p").crossJoin("categories", alias="c").select("p.id", "c.id")

joinSub(query: Any, alias: str, first: Any=None, operator: str | None=None, second: str | None=None) -> Self

Añade una tabla derivada con JOIN INNER; alias es obligatorio y las columnas proyectadas deben ser direccionables.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Acepta un builder, un SelectPlan o un callback síncrono. No existe fullJoinSub en esta API.

from orionis.support.facades import DB
query = DB.table("products", alias="p").joinSub(DB.table("categories").select("id", "name"), "c", "p.category_id", "=", "c.id").select("p.id", "c.name")

leftJoinSub(query: Any, alias: str, first: Any=None, operator: str | None=None, second: str | None=None) -> Self

Añade una tabla derivada con JOIN LEFT OUTER; alias es obligatorio y las columnas proyectadas deben ser direccionables.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Acepta un builder, un SelectPlan o un callback síncrono. No existe fullJoinSub en esta API.

from orionis.support.facades import DB
query = DB.table("products", alias="p").leftJoinSub(DB.table("categories").select("id", "name"), "c", "p.category_id", "=", "c.id").select("p.id", "c.name")

rightJoinSub(query: Any, alias: str, first: Any=None, operator: str | None=None, second: str | None=None) -> Self

Añade una tabla derivada con JOIN RIGHT OUTER; alias es obligatorio y las columnas proyectadas deben ser direccionables.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.
aliasAlias SQL de la proyección o tabla derivada; se utiliza para referenciar su resultado.
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Acepta un builder, un SelectPlan o un callback síncrono. No existe fullJoinSub en esta API.

from orionis.support.facades import DB
query = DB.table("products", alias="p").rightJoinSub(DB.table("categories").select("id", "name"), "c", "p.category_id", "=", "c.id").select("p.id", "c.name")

union(query: Any) -> Self

Combina resultados mediante UNION eliminando duplicados.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Ambas consultas deben tener proyecciones compatibles en número y tipo; la validación final pertenece al motor.

from orionis.support.facades import DB
query = DB.table("products").select("name").union(DB.table("categories").select("name"))

unionAll(query: Any) -> Self

Combina resultados mediante UNION ALL conservando duplicados.

ParámetroUso
queryBuilder, SelectPlan o callback síncrono que configura un builder nuevo. No se espera una coroutine.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Ambas consultas deben tener proyecciones compatibles en número y tipo; la validación final pertenece al motor.

from orionis.support.facades import DB
query = DB.table("products").select("name").unionAll(DB.table("categories").select("name"))

on(first: str, operator: str, second: str) -> Self

Añade una comparación de columnas unida con AND.

ParámetroUso
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Los argumentos first/second son referencias de columna. Para un valor enlazado usa un filtro fuera del ON; JoinClause no ofrece where().

from orionis.orm.query.join_clause import JoinClause
query = JoinClause().on("p.category_id", "=", "c.id")

orOn(first: str, operator: str, second: str) -> Self

Añade una comparación de columnas unida con OR.

ParámetroUso
firstColumna izquierda del ON, o callback síncrono que recibe JoinClause.
operatorOperador de comparación. En condiciones básicas se valida contra SUPPORTED_OPERATORS.
secondReferencia de columna derecha, no un valor de usuario.

Resultado: el mismo builder mutable (Self); no ejecuta SQL.

Los argumentos first/second son referencias de columna. Para un valor enlazado usa un filtro fuera del ON; JoinClause no ofrece where().

from orionis.orm.query.join_clause import JoinClause
query = JoinClause().on("p.category_id", "=", "c.id").orOn("p.category_id", "=", "c.parent_id")

conditions() -> list[JoinCondition]

Devuelve la lista viva de condiciones ON en orden. No ejecuta SQL ni la copia.

Resultado: list[JoinCondition].

Los argumentos first/second son referencias de columna. Para un valor enlazado usa un filtro fuera del ON; JoinClause no ofrece where().

from orionis.orm.query.join_clause import JoinClause
query = JoinClause().on("p.category_id", "=", "c.id").conditions()

Fachada DB · Consultas ORM · Escenario de pruebas