1. Descripción general
La mayoría de los errores de SQL que sobreviven a la revisión de código son errores de agregación. Un número es correcto en la tabla en la que se encuentra, una unión lo copia y el total es incorrecto de forma silenciosa.
BigQuery Graph te permite describir cómo se conectan tus tablas una vez, como un gráfico de propiedades, y, luego, consultar las conexiones. Las medidas de gráficos agregan una cosa más a esa descripción: la agregación en sí. Declaras MEASURE(SUM(streams)) en el nodo que posee el número, y cada consulta que lee el gráfico obtiene el total correcto en el nivel de detalle adecuado: sin trucos de GROUP BY ni CTE que alguien tenga que recordar.
En este codelab, compilarás un catálogo de música de cinco tablas, le agregarás una medida y verás cómo la misma pregunta devuelve dos respuestas diferentes: 12,600 millones con SUM y 5,100 millones con AGG. La brecha es la forma del catálogo: una canción que se encuentra en cuatro playlists se convierte en cuatro filas una vez que se aplana el gráfico, y SUM agrega las cuatro. Luego, aprenderás las reglas que hacen que la segunda sea correcta.

Dónde escribirás
En este lab, se usan exactamente dos lugares, en este orden:
en el que | lo que haces allí | |
1 | Terminal de Cloud Shell | Unos pocos comandos, solo en el paso Configuración |
2 | Consola de BigQuery | Todo lo demás: pegar consultas en el editor de consultas, hacer clic en el modelador de gráficos, chatear con un agente |
Cada instrucción está etiquetada para que siempre sepas a cuál se refiere:
- 👉💻 Cloud Shell: Escribe esto en la terminal de Cloud Shell.
- 👉📋 Editor de consultas: Pega esto en el editor de consultas de BigQuery y haz clic en Ejecutar.
- 👉🌐 Consola: Haz clic en la consola de BigQuery. No es necesario escribir nada, a menos que se indique en el paso.
- 👀: Mira el resultado.
Qué aprenderás
- Cómo declarar una medida en una tabla de nodos, ya sea en el modelador de gráficos visuales o en SQL
- Cómo
GRAPH_EXPANDacopla un grafo en una tabla ancha - Por qué
AGGes la única función que puede leer una medida y qué dice cualquier otro intento - Los seis agregados que admite una medida y cómo realizar operaciones aritméticas entre ellos
- Cómo una medida responde una pregunta agrupada de manera diferente sin cambios
- Opcional: Cómo GQL y la pestaña Graph responden una pregunta que un total no puede responder, y cómo un agente de datos de BigQuery usa tus métricas sin que se le indique nada sobre ellas
Requisitos
- Una Cuenta de Google con facturación disponible y un navegador No necesitas un proyecto de Google Cloud de antemano, ya que la configuración crea uno para ti.
- Solo para el paso de chat opcional: La API de Gemini Data Analytics habilitada y el rol de Creador de agentes de datos de Gemini Data Analytics
No es necesario instalar nada en tu máquina. Todo se ejecuta en Cloud Shell y la consola de BigQuery.
Estado y costo del producto
BigQuery Graph ya está disponible de forma general. Las medidas de gráficos, el modelador visual de gráficos, la visualización de gráficos y el uso de un gráfico como fuente de conocimiento del agente de datos se encuentran en versión preliminar y están cubiertos por las Condiciones de las Ofertas de la fase previa a la DG.
GRAPH_EXPAND y AGG se ejecutan con precios según demanda. Las consultas de GQL (el paso de ruta opcional) requieren una reserva que use la edición Enterprise o Enterprise Plus, según la documentación, por lo que ese paso es opcional.
El conjunto de datos tiene unos pocos kilobytes. Con los precios a pedido, cada consulta se factura con el mínimo de 10 MB, por lo que todo el codelab cuesta una fracción de centavo.
2. Configuración
Este es el único paso que usa Cloud Shell. Crea un proyecto, le aplica la facturación y compila las tablas sin procesar. El gráfico, la medida y cada consulta son tuyos para ejecutarlos después en la consola de BigQuery.
Hay algo que este lab no puede proporcionarte: un proyecto de Google Cloud con la facturación habilitada. El paso 1 te permite obtener una cuenta que puede pagar por él, y el paso 4 convierte esa cuenta en un proyecto. Realízalos en ese orden: cada paso después del 4 lee el proyecto que crea el paso 4.
1 · Obtén una cuenta con facturación (aprox. 1 min)
👉🌐 Haz esto antes que cualquier otra cosa. Accede con una Cuenta de Google que tenga habilitada la facturación. Cualquier cuenta de este tipo funciona. Si no tienes una, comienza una prueba gratuita, que te proporcionará una cuenta de facturación, que es todo lo que se necesita en el paso 4.
2 · Abre Cloud Shell (1 min)
👉🌐 Consola: Haz clic en Activar Cloud Shell en la parte superior de la consola de Google Cloud. Es el ícono con forma de terminal en el encabezado. Se abrirá una terminal en la parte inferior de la página.

👉🌐 Consola: Si se te solicita que autorices en algún momento hoy, haz clic en Autorizar para continuar.
👉💻 Cloud Shell: Verifica con qué cuenta accediste a Cloud Shell:
gcloud auth list
👀 Verifica que tu cuenta esté marcada con un * y que sea la misma con la que accediste en el paso 1. Si no es así, ejecuta gcloud auth login y elige el correcto.
3 · Obtén el lab (alrededor de 1 min)
👉💻 Cloud Shell: Clona el repo:
cd ~
rm -rf ~/bq-graph-measures-lab
git clone https://github.com/cuppibla/bq-graph-measures-lab.git
cd ~/bq-graph-measures-lab
4 · Crea tu proyecto (alrededor de 2 minutos)
👉💻 Cloud Shell: Un script encuentra tu cuenta de facturación, crea un proyecto en ella y dirige Cloud Shell a ese proyecto:
cd ~/bq-graph-measures-lab
./setup_project.sh
👀 Espera un ✓ para la cuenta de facturación que eligió, un ✓ para el proyecto que creó y un final como el siguiente:
Project ready: bq-graph-4271 Next: ./setup.sh
bq-graph-4271 es tu ID del proyecto. El tuyo tendrá dígitos diferentes. Allí suceden cuatro cosas:
facturación | Toma la cuenta de | |
project | Crea | |
selecciona | Escribe el ID en | |
esperas | realiza sondeos hasta que se permita la publicación del proyecto nuevo, durante un máximo de dos minutos | |
🌐 El mismo proyecto ahora está en la consola. Su ID se encuentra en la tarjeta Información del proyecto del panel:

5 · Crea el conjunto de datos (alrededor de 3 min)
👉💻 Cloud Shell: Otra secuencia de comandos compila las tablas:
cd ~/bq-graph-measures-lab
./setup.sh
La secuencia de comandos imprime cada paso a medida que se ejecuta. Qué hace, en orden:
project | Lee el proyecto desde | |
API | habilita | |
dataset | crea el conjunto de datos | |
verificar | cuenta las filas de cada tabla y se detiene si algún recuento es incorrecto | |
👀 Resultado esperado:
BigQuery Graph Measures · setup ✓ project: bq-graph-4271 ✓ BigQuery API enabled Creating dataset music (US) and five tables... ✓ music.Labels 2 rows ✓ music.Artists 3 rows ✓ music.Songs 5 rows ✓ music.Playlists 4 rows ✓ music.PlaylistEntries 10 rows 🎉 ready — open BigQuery Studio: https://console.cloud.google.com/bigquery?project=bq-graph-4271
Terminaste de usar Cloud Shell. Puedes cerrarla.
6 · Abre BigQuery y un editor de consultas
👉🌐 Consola: Haz clic en el vínculo al final del resultado o abre BigQuery desde el menú de navegación. En el panel Explorador de la izquierda, expande tu proyecto: un conjunto de datos music con cinco tablas.

👉🌐 Consola: En la parte superior de BigQuery Studio, en la fila Crear nuevo, haz clic en Consulta en SQL. Se abrirá una pestaña del editor vacía.

Conserva esta pestaña. Todos los bloques 👉📋 de este lab van aquí: Selecciona lo que haya en el editor, pega el bloque nuevo sobre él y haz clic en Ejecutar. El resultado aparece en el panel de abajo.
Conoce las mesas
Dos aspectos de estas tablas son importantes más adelante. Cada tabla declara su clave primaria como NOT ENFORCED: BigQuery no la verifica, pero el gráfico de propiedades que estás a punto de compilar necesita una clave explícita para saber qué identifica una fila. Y la última tabla, PlaylistEntries, es una tabla de unión: Una canción que se encuentra en cuatro playlists tiene cuatro filas en ella. En esa tabla es donde sucede toda la historia.
Las tablas se encadenan de la siguiente manera: un sello discográfico firma artistas, un artista lanza canciones y una canción se coloca en playlists a través de PlaylistEntries. Cymbal Records es propietaria de Ava Sterling y Mina Okafor, y, a través de ellas, de cuatro canciones. Northwind Audio es propietario de Kai Nakamura y de una canción, Midnight Drive.
tabla | filas | clave | lo que contiene |
Etiquetas | 2 |
| Nombre y presupuesto de marketing |
Artistas | 3 |
| nombre, qué etiqueta |
Canciones | 5 |
| título, artista, transmisiones |
Playlists | 4 |
| nombre, seguidores |
PlaylistEntries | 10 |
| qué canción se encuentra en qué playlist |
✅ Punto de control: 🎉 ready en Cloud Shell, cinco tablas en music en el Explorador y una pestaña vacía del editor de consultas abierta.
3. Crea el gráfico: opción A, el modelador visual
Un gráfico de propiedades es una descripción de cómo se conectan las tablas. Puedes hacer clic en el modelador de gráficos visuales (este paso, todo con clics) o escribirlo como SQL (el próximo paso, un solo pegado). Ambos producen el mismo objeto. Haz uno u otro, no ambos.
1. Crea el shell del gráfico
👉🌐 Consola: En BigQuery Studio, en la fila Crear nuevo, abre el menú IA y conocimiento y haz clic en Gráfico.
👉🌐 Consola: Ingresa MusicGraph como el Nombre del grafo y music como el Destino del grafo en el conjunto de datos. La región se completa a partir del conjunto de datos (EE.UU.).
👉🌐 Console: En Data sources, selecciona las cinco tablas (Artists, Labels, PlaylistEntries, Playlists y Songs) y haz clic en Create.

👀 El lienzo se abre con cinco nodos de colores y sin líneas entre ellos. En el panel Details de la derecha, se enumeran Nodos (5) y Aristas (0). Cada nodo ya contiene la clave primaria de su tabla y todas sus columnas como propiedades. Haz clic en cualquier nodo para verlas.

2. Dibuja los cuatro bordes
Una arista es una clave externa, dibujada. Cada una va desde la tabla que contiene la clave hasta la tabla a la que apunta.
👉🌐 Console: Haz clic en New edge. En el cuadro de diálogo Seleccionar tabla, elige PlaylistEntries y haz clic en Agregar. En el panel Agregar arista, haz lo siguiente:
- Establece el Nombre como
EntryToSong. - Haz clic en Agregar clave primaria y acepta
entry_id. - En Fuente, configura Nodo fuente como PlaylistEntries y, luego, usa Agregar columnas a las que se hace referencia en el nodo y Agregar columnas a las que se hace referencia en el borde para elegir
entry_iden ambos casos. - En Target, establece Target node en Songs y, luego, elige
song_idpara Referenced columns in the node y Referenced columns on the edge. - Haz clic en Listo.

👉🌐 Console (consola): Repite tres veces más:
Nombre del borde | tabla | nodo fuente → nodo objetivo | la columna de selección en ambos lados |
| PlaylistEntries | PlaylistEntries → Playlists | fuente |
| Canciones | Canciones → Artistas | fuente |
| Artistas | Artistas → Sellos | fuente |
Deja cada borde sin propiedades adicionales.
👀 El panel Detalles ahora dice Bordes (4), y el lienzo muestra la cadena: Etiquetas ← Artistas ← Canciones ← PlaylistEntries → Playlists.

3. Agrega la medida
👉🌐 Consola: Haz clic en el nodo Canciones y, luego, en el ícono de editar (lápiz) que se encuentra en la parte superior del panel Detalles. En las Propiedades de la etiqueta, haz clic en Agregar propiedad y, luego, en Agregar campo.
👉🌐 Consola: Ingresa total_streams como el Nombre del campo y escribe lo siguiente en el cuadro Expresión:
MEASURE(SUM(streams))
👉🌐 Console: Haz clic en Add y, luego, en Done.

4. Lee el código que escribió y, luego, publícalo.
👉🌐 Consola: Abre la pestaña Código en el panel derecho. El modelador escribió la sentencia CREATE PROPERTY GRAPH por ti. Desplázate hasta el nodo Songs: Su lista de propiedades ahora termina con
MEASURE(SUM(streams)) AS `total_streams`
Esa es toda la función, en una sola línea. Todo lo que sigue a este paso se relaciona con lo que hace esa línea.

👉🌐 Consola: Haz clic en Publicar.
✅ Punto de control: En el Explorador, music ahora tiene una carpeta Graphs que contiene MusicGraph. Haz clic en él: cinco nodos, cuatro aristas y la línea MEASURE(SUM(streams)) en la pestaña Código. Omite el siguiente paso y ve a SUM y AGG, lado a lado.
4. Crea el gráfico (opción B: SQL)
Omite este paso si creaste el gráfico en el modelador.
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
CREATE OR REPLACE PROPERTY GRAPH music.MusicGraph
NODE TABLES (
music.Labels KEY (label_id)
PROPERTIES (label_id, label_name, marketing_budget,
MEASURE(SUM(marketing_budget)) AS total_budget),
music.Artists KEY (artist_id)
PROPERTIES (artist_id, artist_name, label_id,
MEASURE(COUNT(artist_id)) AS artist_count),
music.Songs KEY (song_id)
PROPERTIES (song_id, title, artist_id, streams,
MEASURE(SUM(streams)) AS total_streams,
MEASURE(COUNT(song_id)) AS song_count),
music.Playlists KEY (playlist_id)
PROPERTIES (playlist_id, playlist_name, followers,
MEASURE(SUM(followers)) AS total_followers),
music.PlaylistEntries KEY (entry_id)
PROPERTIES (entry_id, playlist_id, song_id,
MEASURE(COUNT(entry_id)) AS placement_count)
)
EDGE TABLES (
music.PlaylistEntries AS EntryToSong
SOURCE KEY (entry_id) REFERENCES PlaylistEntries(entry_id)
DESTINATION KEY (song_id) REFERENCES Songs(song_id) NO PROPERTIES,
music.PlaylistEntries AS EntryToPlaylist
SOURCE KEY (entry_id) REFERENCES PlaylistEntries(entry_id)
DESTINATION KEY (playlist_id) REFERENCES Playlists(playlist_id) NO PROPERTIES,
music.Songs AS SongToArtist
SOURCE KEY (song_id) REFERENCES Songs(song_id)
DESTINATION KEY (artist_id) REFERENCES Artists(artist_id) NO PROPERTIES,
music.Artists AS ArtistToLabel
SOURCE KEY (artist_id) REFERENCES Artists(artist_id)
DESTINATION KEY (label_id) REFERENCES Labels(label_id) NO PROPERTIES
)
👀 El panel de resultados indica que se creó el gráfico de propiedades.

Leerlo una vez
El gráfico tiene cinco tablas de nodos y cuatro tablas de aristas. Cada tabla de nodos nombra su KEY y enumera su PROPERTIES. Las líneas que comienzan con MEASURE son la parte nueva: cada una ajusta uno de los agregados admitidos alrededor de una propiedad y le asigna un alias, lo cual es obligatorio.
Cada tabla de aristas es una clave externa, escrita de la siguiente manera: SOURCE KEY en la tabla que contiene la clave y DESTINATION KEY en la tabla a la que apunta. NO PROPERTIES significa que la arista no transporta nada por sí misma.
Observa que PlaylistEntries aparece tres veces: una como tabla de nodos y dos veces más como la tabla física detrás de las aristas EntryToSong y EntryToPlaylist. Esto es intencional, y más adelante explicaremos por qué.
Mira lo que creaste
👉🌐 Consola: En el panel Explorador, expande music, luego Gráficos y, por último, haz clic en MusicGraph. La página del gráfico se abre en un lienzo con cinco nodos y cuatro aristas. Haz clic en un nodo para ver sus propiedades. Las medidas se enumeran con su agregado. Abre la pestaña Code para ver la declaración detrás de la imagen.

✅ Punto de control: music tiene una carpeta Graphs que contiene MusicGraph, y la pestaña Code muestra MEASURE(SUM(streams)) AS total_streams.
5. SUM y AGG, uno al lado del otro
Este es todo el codelab en una sola consulta. Ambas columnas intentan responder la misma pregunta (la cantidad total de transmisiones por sello discográfico) a partir de la misma tabla.
Esa tabla es la que produce GRAPH_EXPAND. Aplanar el gráfico: Comienza en una tabla y sigue cada borde hacia afuera como un LEFT JOIN, hasta que cada tabla conectada se encuentra una al lado de la otra en un solo resultado amplio. Una fila por posición, no una por canción, y cada columna se denomina TableLabel_property. Míralo antes de consultarlo.
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
SELECT Labels_label_name, Songs_title, Songs_streams, Playlists_playlist_name
FROM GRAPH_EXPAND("music.MusicGraph")
ORDER BY Songs_title, Playlists_playlist_name
👀 Se espera que haya 10 filas, una para cada posición en PlaylistEntries, que es exactamente lo que cargó la configuración. Neon Summer ocupa cuatro de ellos, uno por cada playlist en la que se encuentra, y Songs_streams registra 2,000,000,000 en cada uno. No hay nada malo con esas filas; las playlists realmente son cuatro. Sin embargo, una columna que pertenece a una canción ahora se repite en las filas que pertenecen a las posiciones, y ese es el problema que mide la siguiente búsqueda.
Ahora, la comparación.
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
SELECT
Labels_label_name,
SUM(Songs_streams) AS with_sum,
AGG(Songs_total_streams) AS with_agg
FROM GRAPH_EXPAND("music.MusicGraph")
GROUP BY 1 ORDER BY 1
👀 Resultado:
Labels_label_name | with_sum | with_agg |
Cymbal Records | 12,600,000,000 | 5,100,000,000 |
Northwind Audio | 9,000,000,000 | 4,500,000,000 |

Verifícalo de forma manual. Las cuatro canciones de Cymbal se transmitieron 2,000 millones, 1,500 millones, 1,200 millones y 400 millones de veces. Eso equivale a 5,100 millones. AGG es correcto. SUM es dos veces y media más grande, y la única canción de Northwind se duplicó.
Tres nuevas sintaxis
GRAPH_EXPAND("music.MusicGraph")es una función con valores de tabla que convierte el grafo en una tabla ancha siguiendo cada borde como unLEFT JOIN. Todas las columnas se llamanTableLabel_property, por lo queSongs_streamses la columna sin procesar de la tabla Songs ySongs_total_streamses la medida que declaraste.SUM(Songs_streams)es SQL común sobre esa tabla ancha y hereda cada duplicado que produjo el aplanamiento.AGG(Songs_total_streams)evalúa la medida de la forma en que se declaró:SUM(streams)una vez porsong_id, sin importar cuántas filas ocupe una canción en la tabla ancha.
✅ Punto de control: Dos etiquetas, dos columnas y los números de with_agg coinciden con el recuento manual.
6. Por qué SUM sobrecuenta
Toma una canción y observa qué hacen esas uniones con ella.
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
SELECT 'BEFORE - the Songs table' AS step, title, streams, CAST(NULL AS STRING) AS playlist
FROM music.Songs WHERE title = 'Neon Summer'
UNION ALL
SELECT 'AFTER - joined to playlists', s.title, s.streams, pl.playlist_name
FROM music.Songs s
LEFT JOIN music.PlaylistEntries e ON e.song_id = s.song_id
LEFT JOIN music.Playlists pl ON pl.playlist_id = e.playlist_id
WHERE s.title = 'Neon Summer'
ORDER BY step DESC, playlist
👀 Resultado:
paso | título | transmisiones | playlist |
ANTES: La tabla Songs | Verano neón | 2,000,000,000 | null |
DESPUÉS: Se unió a playlists | Verano neón | 2,000,000,000 | Gym Pump |
DESPUÉS: Se unió a playlists | Verano neón | 2,000,000,000 | Hot Right Now |
DESPUÉS: Se unió a playlists | Verano neón | 2,000,000,000 | Rising Pop |
DESPUÉS: Se unió a playlists | Verano neón | 2,000,000,000 | Música para viajar |

Una fila se convirtió en cuatro. El recuento de transmisiones no cambió, sino que se copió. Suma lo que hacen las copias para Cymbal Records: Neon Summer 2.0 mil millones en cuatro playlists son 8.0, Paper Crown 1.5 mil millones en dos son 3.0, Double Shot 1.2 en una, Slow Arrow 0.4 en una. Es decir, 12,600 millones, el número SUM que se devolvió. Midnight Drive de Northwind se encuentra en dos playlists, por lo que 4,500 millones se convirtieron en 9,000 millones.
Esto se denomina fan-out y no es un error en la unión. Las filas de la playlist son reales. El error consiste en sumar un número que pertenece a una canción en filas que pertenecen a posiciones.
La medida lo corrige porque se declaró en el nodo Songs junto con KEY (song_id). La clave es el grano. Cuando AGG evalúa total_streams, agrega los datos una vez por clave de canción y, solo entonces, los resume según el criterio de agrupación que hayas elegido.
Qué cambió
Antes escribías | Con una medida |
|
|
|
|
Tres |
|
Un CTE que se agrega antes de unirse | Nada. El |
✅ Punto de control: Cinco filas: una ANTES, cuatro DESPUÉS.Puedes reconstruir 12,600 millones a partir de ellas.
7. La regla: Solo AGG lee una medida
Las medidas tienen su propio tipo, MEASURE, y exactamente una función lo acepta. Las cuatro consultas que se muestran a continuación fallan a propósito. Ejecuta cada una y lee el error en rojo. Estas son las cuatro formas que todos prueban primero, y saber lo que dicen ahorra tiempo más adelante.
👉📋 Editor de consultas: AGG en una columna simple:
SELECT AGG(Songs_streams) FROM GRAPH_EXPAND("music.MusicGraph")
👀 No matching signature for aggregate function AGG ... Argument 1: expected MEASURE

👉📋 Editor de consultas: Una columna de métricas sin AGG:
SELECT Songs_total_streams FROM GRAPH_EXPAND("music.MusicGraph") LIMIT 1
👀 Returning expressions of type MEASURE is not allowed

👉📋 Editor de consultas: Es una medida a la que se hace referencia en GQL y que nunca ve medidas (esta es una consulta de GQL; consulta la nota de edición en la descripción general):
GRAPH music.MusicGraph
MATCH (s:Songs)
RETURN s.total_streams
LIMIT 1
👀 total_streams is not exposed by element type GRAPH_NODE(...)

👉📋 Editor de consultas: SUM sobre una columna de medición, la tentadora:
SELECT Labels_label_name, SUM(Songs_total_streams)
FROM GRAPH_EXPAND("music.MusicGraph")
GROUP BY 1
👀 MEASURE-typed arguments are only permitted in the AGG function

Por lo tanto, el sistema de tipos aplica la regla por ti. Una medida solo se puede ver a través de GRAPH_EXPAND y solo se puede leer a través de AGG. El recuento excesivo de 12,600 millones anterior solo puede provenir de la suma de la columna sin procesar, nunca de un manejo incorrecto de la métrica.
✅ Punto de control: Cuatro errores rojos, y puedes decir qué regla aplica cada uno.
8. Cada agregado que admite una medida
MEASURE() incluye uno de los seis agregados: SUM, AVG, MIN, MAX, COUNT y COUNT(DISTINCT). Vuelve a crear el gráfico con los seis nodos en el nodo Songs. Los bordes permanecen NO PROPERTIES, que es la práctica recomendada documentada cuando un borde comparte su tabla física con un nodo.
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
CREATE OR REPLACE PROPERTY GRAPH music.MusicGraph
NODE TABLES (
music.Labels KEY (label_id)
PROPERTIES (label_id, label_name, marketing_budget,
MEASURE(SUM(marketing_budget)) AS total_budget),
music.Artists KEY (artist_id)
PROPERTIES (artist_id, artist_name, label_id,
MEASURE(COUNT(artist_id)) AS artist_count),
music.Songs KEY (song_id)
PROPERTIES (song_id, title, artist_id, streams,
MEASURE(SUM(streams)) AS total_streams,
MEASURE(AVG(streams)) AS avg_streams,
MEASURE(MIN(streams)) AS min_streams,
MEASURE(MAX(streams)) AS max_streams,
MEASURE(COUNT(song_id)) AS song_count,
MEASURE(COUNT(DISTINCT artist_id)) AS distinct_artists),
music.Playlists KEY (playlist_id)
PROPERTIES (playlist_id, playlist_name, followers,
MEASURE(SUM(followers)) AS total_followers),
music.PlaylistEntries KEY (entry_id)
PROPERTIES (entry_id, playlist_id, song_id,
MEASURE(COUNT(entry_id)) AS placement_count)
)
EDGE TABLES (
music.PlaylistEntries AS EntryToSong
SOURCE KEY (entry_id) REFERENCES PlaylistEntries(entry_id)
DESTINATION KEY (song_id) REFERENCES Songs(song_id) NO PROPERTIES,
music.PlaylistEntries AS EntryToPlaylist
SOURCE KEY (entry_id) REFERENCES PlaylistEntries(entry_id)
DESTINATION KEY (playlist_id) REFERENCES Playlists(playlist_id) NO PROPERTIES,
music.Songs AS SongToArtist
SOURCE KEY (song_id) REFERENCES Songs(song_id)
DESTINATION KEY (artist_id) REFERENCES Artists(artist_id) NO PROPERTIES,
music.Artists AS ArtistToLabel
SOURCE KEY (artist_id) REFERENCES Artists(artist_id)
DESTINATION KEY (label_id) REFERENCES Labels(label_id) NO PROPERTIES
)

Ahora, léelos todos. Cada medida pasa por AGG, y la última columna muestra que los resultados de AGG son valores ordinarios con los que puedes hacer operaciones aritméticas. El gráfico acaba de cambiar, así que primero desmarca Usar resultados almacenados en caché (Más → Configuración de consulta).
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
SELECT
Labels_label_name,
AGG(Songs_total_streams) AS total_streams,
AGG(Songs_avg_streams) AS avg_streams,
AGG(Songs_min_streams) AS min_streams,
AGG(Songs_max_streams) AS max_streams,
AGG(Songs_song_count) AS songs,
AGG(Songs_distinct_artists) AS artists,
AGG(Songs_total_streams) / AGG(Songs_song_count) AS streams_per_song
FROM GRAPH_EXPAND("music.MusicGraph")
GROUP BY 1
ORDER BY 1
👀 Resultado:
Labels_label_name | total_streams | avg_streams | min_streams | max_streams | canciones | artistas | streams_per_song |
Cymbal Records | 5,100,000,000 | 1,275,000,000 | 400,000,000 | 2,000,000,000 | 4 | 2 | 1,275,000,000 |
Northwind Audio | 4,500,000,000 | 4,500,000,000 | 4,500,000,000 | 4,500,000,000 | 1 | 1 | 4,500,000,000 |

Cada número se calcula en función de cuatro canciones para Cymbal y una para Northwind, no en función de las diez filas de posiciones. AVG en particular habría sido incorrecto de la otra manera: promediar la columna sin procesar en las filas de la posición da 1,575000000 para Cymbal, porque los 2,000,000,000 de Neon Summer se cuentan cuatro veces.
Por lo tanto, "reemplazar SUM por AGG" son en realidad dos decisiones. Cuando declaras la medida, aún eliges cuál de los seis agregados es. Cuando la lees, la función siempre es AGG.
✅ Verificación: Una fila por etiqueta, siete números cada una y streams_per_song igual a avg_streams.
9. Cambia la agrupación, no la métrica
La misma medida responde una pregunta diferente. Agrupar por playlist en lugar de etiqueta
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
SELECT
Playlists_playlist_name,
AGG(Songs_total_streams) AS streams,
AGG(Songs_song_count) AS songs
FROM GRAPH_EXPAND("music.MusicGraph")
GROUP BY 1
ORDER BY 2 DESC
👀 Resultado:
Playlists_playlist_name | transmisiones | canciones |
Música para viajar | 6,900,000,000 | 3 |
Gym Pump | 6,500,000,000 | 2 |
Hot Right Now | 4,700,000,000 | 3 |
Rising Pop | 3,500,000,000 | 2 |

Las dos líneas de AGG son byte por byte las de SUM y AGG, una al lado de la otra. Solo se movió el GROUP BY. Road Trip incluye Neon Summer, Midnight Drive y Slow Arrow, y cada canción se cuenta una vez dentro de esa playlist, que es exactamente lo que debería significar "las transmisiones que llegan a esta playlist".
La persona que escribió la medida decidió la granularidad una vez. Todas las consultas posteriores, de cualquier persona, la heredan.
✅ Punto de control: Road Trip en primer lugar con 6,900 millones.
10. Consulta lo que te ofrece GRAPH_EXPAND
No es necesario que ejecutes GRAPH_EXPAND para conocer su forma. El procedimiento del sistema BQ.SHOW_GRAPH_EXPAND_SCHEMA escribe la lista de columnas en una variable.
👉📋 Editor de consultas: Pega las tres líneas y, luego, haz clic en Ejecutar:
DECLARE schema STRING DEFAULT '';
CALL BQ.SHOW_GRAPH_EXPAND_SCHEMA('music.MusicGraph', schema);
SELECT schema;
👀 El resultado es una cadena JSON. Cada campo tiene un nombre, un tipo y un modo, y cada columna de medida incluye "is_measure": true. Para el gráfico que acabas de crear, obtendrás los siguientes resultados, entre otros:
nombre | tipo | is_measure | |
Songs_title | STRING | ||
Songs_streams | INTEGER | ||
Songs_total_streams | INTEGER | verdadero | |
Songs_avg_streams | FLOAT | verdadero | |
Songs_distinct_artists | INTEGER | verdadero | |
PlaylistEntries_placement_count | INTEGER | verdadero | |

Aquí también se muestran las descripciones o los sinónimos que establezcas en una propiedad. El paso de chat opcional muestra quién lee esos mensajes.
✅ Punto de control: Una cadena JSON con is_measure en cada columna que declaraste con MEASURE.
11. Qué necesita GRAPH_EXPAND de la forma de un grafo
No hay nada que ejecutar en este paso, solo leer. GRAPH_EXPAND crea su tabla ancha con una cadena de LEFT JOIN, comenzando con una tabla y siguiendo los bordes hacia afuera. De ello se derivan tres reglas, y MusicGraph satisface todas ellas.

Exactamente una tabla de nodos raíz. La raíz es la tabla de nodos cuya clave no aparece en ninguna otra tabla, es decir, aquella a la que no apunta ninguna arista. En MusicGraph, es PlaylistEntries: la fuente de dos aristas y el destino de ninguna. La tabla ancha tiene 10 filas, una por posición.
Cada arista es de muchos a uno, del origen al destino. Cada entrada tiene una canción y una playlist, cada canción tiene un artista y cada artista tiene un sello discográfico. Por eso, la tabla ancha nunca se extiende más allá de las filas de la raíz. No aparecen los datos a los que no puede acceder la raíz: Una canción sin posiciones faltaría en la tabla amplia.
Las relaciones de varios a varios se convierten en un nodo. Las canciones y las playlists tienen una relación de muchos a muchos. Si declaraste la tabla de unión como una sola arista de Songs a Playlists, GRAPH_EXPAND la ignoraría por ser ambigua y, sin aristas utilizables, fallaría. Promocionar PlaylistEntries a una tabla de nodos con demasiados bordes de muchos a uno es el patrón documentado, y es lo que hiciste cuando compilaste el gráfico.
12. (OPCIONAL) Rutas de acceso con GQL
Hasta ahora, todas las preguntas tuvieron un número como respuesta. Este no lo hace. ¿A dónde llegan las transmisiones de Cymbal? es una pregunta sobre las rutas a través del gráfico, y un total no puede responderla, ya que, cuando sumas, la ruta desaparece.
1. Pregunta dónde se publican las transmisiones
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
GRAPH music.MusicGraph
MATCH (l:Labels)<-[:ArtistToLabel]-(a:Artists)<-[:SongToArtist]-(s:Songs)
<-[:EntryToSong]-(e:PlaylistEntries)-[:EntryToPlaylist]->(pl:Playlists)
WHERE l.label_name = 'Cymbal Records'
RETURN pl.playlist_name, pl.followers,
SUM(s.streams) AS streams_reaching_this_playlist,
STRING_AGG(s.title, ', ') AS songs
GROUP BY pl.playlist_name, pl.followers
ORDER BY streams_reaching_this_playlist DESC
👀 Habrá cuatro playlists:
pl.playlist_name | pl.followers | streams_reaching_this_playlist | canciones |
Hot Right Now | 35,000,000 | 4,700,000,000 | Doble disparo, Verano neón, Corona de papel |
Rising Pop | 2,000,000 | 3,500,000,000 | Neon Summer, Paper Crown |
Música para viajar | 5,000,000 | 2,400,000,000 | Neon Summer, Slow Arrow |
Gym Pump | 3,000,000 | 2,000,000,000 | Verano neón |

Lee la línea MATCH como una oración: comienza en una etiqueta, retrocede a sus artistas, luego a sus canciones, luego a las entradas de la playlist en las que se encuentran esas canciones y, luego, avanza a las playlists. Las flechas indican la dirección en la que se declararon los bordes; <- recorre uno hacia atrás.
Ahora suma esa tercera columna. 12,600 millones: Es el número que te dio SUM en el paso cuatro, el que era incorrecto.
Aquí está a la derecha. En ese entonces, la pregunta era cuánto se reproducía Cymbal, y una canción se contaba una vez, sin importar cuántas playlists la tuvieran. Esta pregunta se refiere a dónde llegan esos streams, y una canción en cuatro playlists llega genuinamente a cuatro públicos. La duplicación que produce GRAPH_EXPAND es un error para una pregunta y la respuesta para la otra. AGG nunca se trató de que los duplicados fueran malos, sino de hacer coincidir la aritmética con la pregunta.
2. Devuelve las rutas en sí.
Descarta la agregación y solicita las rutas.
👉📋 Editor de consultas: Pega y, luego, haz clic en Ejecutar:
GRAPH music.MusicGraph
MATCH p = (l:Labels)<-[:ArtistToLabel]-(a:Artists)<-[:SongToArtist]-(s:Songs)
<-[:EntryToSong]-(e:PlaylistEntries)-[:EntryToPlaylist]->(pl:Playlists)
WHERE l.label_name = 'Cymbal Records'
RETURN TO_JSON(p) AS path
p = nombra toda la coincidencia y TO_JSON la renderiza.
👀 Se espera 8 filas y una columna path. Cada celda es un array JSON de los nodos y los bordes a lo largo de una ruta, y cada nodo contiene sus labels y properties.

Ocho filas para cuatro canciones, ya que existe una ruta por posición, no por canción.
3. Abre la pestaña Gráfico
👉🌐 Consola: Sobre los resultados, haz clic en Gráfico.
Esta pestaña solo aparece cuando un resultado contiene elementos de gráfico. La consulta anterior devolvió números, por lo que no tenía una pestaña Gráfico. Esta devuelve rutas, por lo que sí la tiene.

Obtendrás la esquina del gráfico de Cymbal dibujada como un diseño de fuerzas, con un recuento de los nodos y los bordes en la vista, y un chip por etiqueta. Arrastra un nodo para separar el diseño o haz clic en uno para leer sus propiedades.
✅ Punto de control: La tercera columna de la primera consulta suma 12, 600 millones, la segunda consulta devuelve 8 rutas y la pestaña Gráfico las dibuja.
13. (OPCIONAL) Chatea con el gráfico
No hay SQL en este paso. Los agentes de datos de BigQuery pueden usar un gráfico como fuente de conocimiento, y la documentación indica que usan medidas para la agregación de varios niveles. Veamos si eso es cierto.
1. Crea el agente
👉🌐 Consola: En el menú de navegación de BigQuery, a la izquierda, haz clic en Agentes, luego en Catálogo de agentes y, por último, en Crear agente.
👉🌐 Consola: Escribe Music graph agent en Nombre del agente y esto en Descripción del agente:
Ask questions about labels, artists, songs and playlists in the music property graph.
👉🌐 Consola: En Fuentes de conocimiento, haz clic en Agregar fuente. En el diálogo Seleccionar fuentes, expande tu proyecto, expande music, expande Gráficos, marca MusicGraph y haz clic en Confirmar.
👀 El botón Agregar fuente se muestra en gris. Un agente puede contener como máximo un gráfico y no puede combinar gráficos con tablas.

👉🌐 Consola: Deja Región como se estableció desde la ubicación del gráfico. Haz clic en Guardar y, luego, en Publicar. En el panel Canales de publicación, haz clic en Publicar agente y cierra la confirmación.
2. Haz la pregunta
👉🌐 Console: Haz clic en Create conversation. Se abrirá una página de chat. Escribe lo siguiente en el cuadro Hacer una pregunta que se encuentra en la parte inferior y presiona Intro:
For each label, show total streams and how many playlists their songs are on
👀 El agente devuelve una tabla y un resumen de una oración:
label_name | total_streams | playlist_placements |
Cymbal Records | 5,100,000,000 | 8 |
Northwind Audio | 4,500,000,000 | 2 |

5,100 millones Nadie le dijo al agente sobre el fan-out, y no se incluyó en él.
3. Lee la búsqueda que escribió.
👉🌐 Consola: En el menú de navegación, haz clic en Explorador de trabajos y, luego, en el trabajo más reciente. Sus etiquetas incluyen ca-bq-job: true y data-agent-id con el ID de tu agente, y su consulta es la siguiente:
SELECT
Labels_label_name AS label_name,
AGG(Songs_total_streams) AS total_streams,
AGG(PlaylistEntries_placement_count) AS playlist_placements
FROM GRAPH_EXPAND("music.MusicGraph")
GROUP BY label_name
ORDER BY total_streams DESC

Usó GRAPH_EXPAND y AGG por sí solo, ya que las medidas estaban en el esquema que leyó. No se menciona nada sobre ellos en la descripción del agente.
✅ Punto de control: 5.100 millones en la respuesta del chat y AGG(...) en el SQL del trabajo.
14. Limpia
👉💻 Cloud Shell: Suelta el conjunto de datos, sus tablas y el gráfico de propiedades:
cd ~/bq-graph-measures-lab
./cleanup.sh
👀 Se espera ✓ dropped YOUR_PROJECT_ID.music (tables and graph).
Si creaste el agente de datos opcional, bórralo en la consola en Agentes → Catálogo de agentes. Y si ./setup_project.sh creó un proyecto solo para este lab, la limpieza más ordenada de todas es cerrar todo el proyecto. El ID se encuentra en ~/project_id.txt.
15. Felicitaciones
Declaraste una línea, MEASURE(SUM(streams)), y cambió 12,600 millones a 5,100 millones, para ti y para cada búsqueda que alguien escriba en ese gráfico después, incluidas las que escriba un agente.
Qué aprendiste
- Una medida es un agregado declarado en un nodo, junto al
KEYque establece su granularidad. GRAPH_EXPANDacopla el gráfico en una tabla ancha conTableLabel_propertycolumnas.AGGes la única función que lee una medida, y el sistema de tipos la aplica de cuatro maneras diferentes.- Hay seis agregados disponibles, y los resultados de
AGGson valores ordinarios que puedes dividir. - Cambiar el
GROUP BYvuelve a hacer la pregunta sin modificar la medida. GRAPH_EXPANDquiere una raíz, bordes de muchos a uno y uniones promovidas a nodos.
La tabla de decisiones
Síntoma | Causa | Corregir |
Un total demasiado grande |
| declarar una medida y leerla con |
"Se esperaba MEASURE, se encontró INT64" |
| usar |
"No se permiten expresiones que devuelvan el tipo MEASURE" | columna de medición sin | Unirlo: |
"No se expone por el tipo de elemento" | Medida a la que se hace referencia en GQL | Las medidas en vivo se retrasan |
| Intersección modelada como una arista | Promocionar la tabla de unión a un nodo |
Un número anterior después de cambiar el gráfico | resultado almacenado en caché | Desmarca Usar resultados almacenados en caché. |
Temas que no abordamos (a propósito)
Descripciones y sinónimos en propiedades, consultas verificadas y glosarios para agentes de datos, GQL más allá de un MATCH y medidas en más de un gráfico. Cada uno es un lab independiente.
Más información
- Trabaja con medidas
- Crea y consulta un gráfico de propiedades
- Descripción general de Conversational Analytics
- El repo del lab: Todas las consultas de este codelab, numeradas por paso