En este artículo te quiero compartir la manera en la que yo uso las funciones json_object y json_group_array.

Siento que estas 2 funciones son muy útiles para agrupar datos.

Le he encontrado 2 usos que permiten traer más filas en una sola fila. Esto también puede conocerse como obtener varias filas de subconsulta en una columna o traer muchas filas agrupadas en un campo en consulta SQL, similar a lo que hicimos con PostgreSQL

Usando json_object

La función json_object de SQLite3 te permite codificar un objeto JSON, por ejemplo:

SELECT
    entradas.id,
    fecha,
    id_usuario,
    json_object('id', usuarios.id, 'nombre', usuarios.nombre) AS usuarioComoJson
FROM
    entradas
    INNER JOIN usuarios ON usuarios.id = entradas.id_usuario

Fíjate sobre todo en la invocación a json_object:

    json_object('id', usuarios.id, 'nombre', usuarios.nombre) AS usuarioComoJson

Eso me va a devolver todos los datos del usuario en una sola fila. Esto es perfecto, ya que luego en el lado del cliente solo debo decodificar el JSON y puedo usar el objeto.

La salida sería:

1	2025-10-06T18:36:59	1	{"id":1,"nombre":"parzibyte"}
2	2025-10-06T18:37:04	1	{"id":1,"nombre":"parzibyte"}
3	2025-10-06T19:11:17	1	{"id":1,"nombre":"parzibyte"}
4	2025-10-06T19:16:22	1	{"id":1,"nombre":"parzibyte"}
5	2025-10-06T19:26:13	1	{"id":1,"nombre":"parzibyte"}
6	2025-10-06T19:26:53	1	{"id":1,"nombre":"parzibyte"}

Además, si añado una propiedad, por ejemplo, correo solo debería modificar así:

    json_object('id', usuarios.id, 'nombre', usuarios.nombre, 'correo', usuarios.correo) AS usuarioComoJson

Si esta función no existiera también sería posible hacerlo pero no quedaría agrupado de una manera tan bonita, tendría que hacer algo así:

SELECT
    entradas.id,
    fecha,
    usuarios.id as id_usuario,
    usuarios.nombre
FROM
    entradas
    INNER JOIN usuarios ON usuarios.id = entradas.id_usuario

Y el usuario no vendría agrupado, además de que los campos podrían colisionar y tendría que ser más específico. Además, si luego quiero traer también otra tabla, sería así con JSON:

SELECT
    entradas.id,
    fecha,
    id_usuario,
    json_object('id', usuarios.id, 'nombre', usuarios.nombre) AS usuarioComoJson
    json_object('id', otra_tabla.id, 'otro_campo', otra_tabla.otro_campo) AS otroCampoComoJson
FROM
    entradas
    INNER JOIN usuarios ON usuarios.id = entradas.id_usuario
    INNER JOIN otra_tabla ON otra_tabla.id = entradas.id_otra_tabla

Desconozco si los maestros de SQL conocen otra técnica pero para mí esta función me facilita mucho las cosas, sobre todo en conjunto con la siguiente función.

Usando json_group_array

Esta es otra función que me gusta mucho porque no solamente permite agrupar un objeto, permite agrupar todo un arreglo de filas en un solo campo.

Veamos un ejemplo:

SELECT
    entradas.id,
    fecha,
    id_usuario,
    json_object('id', usuarios.id, 'nombre', usuarios.nombre) AS usuarioComoJson,
    (
        select
            json_group_array(
                json_object(
                    'id',
                    productos_entradas.id,
                    'nombre',
                    productos.nombre,
                    'cantidad',
                    productos_entradas.cantidad
                )
            )
        from
            productos_entradas
            inner join productos ON productos.id = productos_entradas.id_producto
        where
            productos_entradas.id_entrada = entradas.id
    ) as productosComoJson
FROM
    entradas
    INNER JOIN usuarios ON usuarios.id = entradas.id_usuario

Centrémonos de nuevo en la función json_group_array:

select
    json_group_array(
        json_object(
            'id',
            productos_entradas.id,
            'nombre',
            productos.nombre,
            'cantidad',
            productos_entradas.cantidad
        )
    )
from
    productos_entradas
    inner join productos ON productos.id = productos_entradas.id_producto
where
    productos_entradas.id_entrada = entradas.id

Esto nos permite agrupar cualquier cantidad de filas en una sola propiedad usando json_group_array y json_object. Cada objeto creado con json_object será colocado en el arreglo creado de json_group_array

La salida al ejecutar la consulta es:

1	2025-10-06T18:36:59	1	{"id":1,"nombre":"parzibyte"}	[{"id":1,"nombre":"KG pollo crudo","cantidad":1.0}]
2	2025-10-06T18:37:04	1	{"id":1,"nombre":"parzibyte"}	[{"id":2,"nombre":"KG pollo crudo","cantidad":1.0},{"id":3,"nombre":"1","cantidad":1.0}]
3	2025-10-06T19:11:17	1	{"id":1,"nombre":"parzibyte"}	[{"id":4,"nombre":"KG papa","cantidad":4.0},{"id":5,"nombre":"Rebanada jamón","cantidad":3.0},{"id":6,"nombre":"KG zanahoria","cantidad":2.0}]
4	2025-10-06T19:16:22	1	{"id":1,"nombre":"parzibyte"}	[{"id":7,"nombre":"KG papa","cantidad":10.0},{"id":8,"nombre":"KG zanahoria","cantidad":0.5}]
5	2025-10-06T19:26:13	1	{"id":1,"nombre":"parzibyte"}	[{"id":9,"nombre":"KG papa","cantidad":13.0},{"id":10,"nombre":"KG zanahoria","cantidad":0.5}]
6	2025-10-06T19:26:53	1	{"id":1,"nombre":"parzibyte"}	[{"id":11,"nombre":"KG papa","cantidad":1.0},{"id":12,"nombre":"Rebanada jamón","cantidad":1.0},{"id":13,"nombre":"KG zanahoria","cantidad":1.0}]

Como puedes ver tengo varias filas de la tabla productos_entradas en una sola celda de mi consulta principal con SQLite3.

También podemos anidar las funciones.

Sobre el rendimiento

Lo mostrado aquí debe ser un poco pesado, pues se van a estar creando objetos JSON por cada fila. Dependiendo de la cantidad de filas esto puede afectar al rendimiento.

Yo lo hago de esta manera porque debo mostrar todos los productos que se registraron en una entrada.

Otra opción sería consultar todas las entradas, recorrerlas y por cada una de ellas asignarle la propiedad productos que sería el resultado de ejecutar otra consulta, pero ahí ejecutaríamos una consulta por cada valor existente en entradas así que yo prefiero esta opción ya que la paginación y filtros hacen que las filas devueltas sean pocas.

Si el post ha sido de tu agrado te invito a que me sigas para saber cuando haya escrito un nuevo post, haya actualizado algún sistema o publicado un nuevo software. Facebook | X | Instagram | Telegram | También estoy a tus órdenes para cualquier contratación en mi página de contacto