Panoramica delle query sul grafico

BigQuery Graph consente di scrivere query sui grafi per trovare pattern di nodi, archi e percorsi e attraversare le relazioni utilizzando Graph Query Language (GQL). Gli esempi in questo documento fanno riferimento a un grafo denominato FinGraph, che mostra le relazioni tra le persone, gli account di loro proprietà e i trasferimenti tra gli account. Per informazioni sulla definizione del grafico, consulta l'esempio di FinGraph.

Struttura della query

Una query del grafico è costituita dal nome del grafico, seguito da una o più istruzioni di query lineari. Ogni query lineare contiene una o più istruzioni, che ti consentono di lavorare con i dati del grafo per trovare corrispondenze di pattern, definire variabili, filtrare e trasformare i dati intermedi e restituire i risultati. Puoi eseguire una query sul grafo nello stesso modo in cui esegui una query SQL in BigQuery.

Esempio di struttura di query del grafo.
Un esempio della struttura di una query di grafo.

Corrispondenza di pattern di grafi

Corrispondenza di pattern del grafo: trova pattern specifici all'interno del grafo. I pattern più semplici sono i pattern degli elementi, come i pattern dei nodi che corrispondono ai nodi e i pattern degli archi che corrispondono agli archi.

Pattern dei nodi

Un pattern di nodi corrisponde ai nodi nel grafo. Questo pattern contiene parentesi corrispondenti, che possono facoltativamente includere una variabile del pattern del grafo, un'espressione di etichetta e filtri delle proprietà.

Trova tutti i nodi

La seguente query restituisce tutti i nodi del grafico. La variabile n, una variabile del pattern del grafico, si associa ai nodi corrispondenti. In questo caso, il pattern del nodo corrisponde a tutti i nodi del grafo.

GRAPH graph_db.FinGraph
MATCH (n)
RETURN LABELS(n) AS label, n.id;

Questa query restituisce label e id:

label id
Account 7
Account 16
Account 20
Person 1
Person 2
Person 3

Trova tutti i nodi con un'etichetta specifica

La seguente query corrisponde a tutti i nodi del grafico che hanno l'etichetta Person. La query restituisce l'etichetta e alcune proprietà dei nodi corrispondenti.

GRAPH graph_db.FinGraph
MATCH (p:Person)
RETURN LABELS(p) AS label, p.id, p.name;

Questa query restituisce le seguenti proprietà dei nodi corrispondenti:

label id name
Person 1 Alex
Person 2 Dana
Person 3 Lee

Trova tutti i nodi corrispondenti a un'espressione di etichetta

Puoi creare un'espressione di etichetta con uno o più operatori logici. Ad esempio, la seguente query corrisponde a tutti i nodi del grafico che hanno l'etichetta Person o Account. La variabile del pattern del grafo n espone tutte le proprietà dei nodi con l'etichetta Person o Account.

GRAPH graph_db.FinGraph
MATCH (n:Person|Account)
RETURN LABELS(n) AS label, n.id, n.birthday, n.create_time;

Nei risultati di questa query, tieni presente quanto segue:

  • Tutti i nodi hanno la proprietà id.
  • I nodi che corrispondono all'etichetta Account hanno la proprietà create_time, ma non la proprietà birthday. La proprietà birthday è NULL per questi nodi.
  • I nodi che corrispondono all'etichetta Person hanno la proprietà birthday, ma non la proprietà create_time. La proprietà create_time è NULL per questi nodi.
label id birthday create_time
Account 7 NULL 2020-01-10T14:22:20.222Z
Account 16 NULL 2020-01-28T01:55:09.206Z
Account 20 NULL 2020-02-18T13:44:20.655Z
Person 1 1991-12-21T08:00:00Z NULL
Person 2 1980-10-31T08:00:00Z NULL
Person 3 1986-12-07T08:00:00Z NULL

Trova tutti i nodi corrispondenti all'espressione dell'etichetta e al filtro delle proprietà

La seguente query corrisponde a tutti i nodi del grafico che hanno l'etichetta Person e la proprietà id uguale a 1:

GRAPH graph_db.FinGraph
MATCH (p:Person {id: 1})
RETURN LABELS(p) AS label, p.id, p.name, p.birthday;

Il risultato è simile al seguente:

label id name birthday
Person 1 Alex 1991-12-21T08:00:00Z

Puoi utilizzare la clausola WHERE per formare condizioni di filtro più complesse su etichette e proprietà.

La seguente query utilizza la clausola WHERE per filtrare i nodi per i quali la proprietà birthday è precedente a 1990-01-10:

GRAPH graph_db.FinGraph
MATCH (p:Person WHERE p.birthday < '1990-01-10')
RETURN LABELS(p) AS label, p.name, p.birthday;

Il risultato è simile al seguente:

label name birthday
Person Dana 1980-10-31T08:00:00Z
Person Lee 1986-12-07T08:00:00Z

Pattern di bordi

Un pattern di arco corrisponde ad archi o relazioni tra nodi. I pattern dei bordi sono racchiusi tra parentesi quadre ([]) e includono simboli come -, -> o <- per indicare le direzioni. Un pattern di arco può includere facoltativamente una variabile di pattern di grafo da associare agli archi corrispondenti.

Trova tutti gli archi con etichette corrispondenti

Questa query restituisce tutti gli archi nel grafico con l'etichetta Transfers. La query associa la variabile del pattern del grafico e agli archi corrispondenti.

GRAPH graph_db.FinGraph
MATCH -[e:Transfers]->
RETURN e.Id as src_account, e.order_number;

Il risultato è simile al seguente:

src_account order_number
7 304330008004315
7 304120005529714
16 103650009791820
20 304120005529714
20 302290001255747

Trova tutti gli archi corrispondenti all'espressione dell'etichetta e al filtro delle proprietà

Il pattern di arco nella query seguente utilizza un'espressione di etichetta e un filtro delle proprietà per trovare tutti gli archi con etichetta Transfers che corrispondono a un numero di ordine specificato:

GRAPH graph_db.FinGraph
MATCH -[e:Transfers {order_number: "304120005529714"}]->
RETURN e.Id AS src_account, e.order_number;

Il risultato è simile al seguente:

src_account order_number
7 304120005529714
20 304120005529714

Trova tutti gli archi utilizzando qualsiasi pattern di arco di direzione

Puoi utilizzare il pattern di arco any direction (-[]-) in una query per trovare archi corrispondenti in entrambe le direzioni. La seguente query trova tutti i trasferimenti con un account bloccato:

GRAPH graph_db.FinGraph
MATCH (account:Account)-[transfer:Transfers]-(:Account {is_blocked:true})
RETURN transfer.order_number, transfer.amount;

Il risultato è simile al seguente:

order_number amount
304330008004315 300
304120005529714 100
103650009791820 300
302290001255747 200

Pattern del percorso

Un pattern di percorso è costituito da pattern di nodi e archi alternati.

Trova tutti i percorsi da un nodo specifico utilizzando un pattern di percorso

La seguente query trova tutti i trasferimenti a un account avviati da un account di proprietà di Person con id uguale a 2.

Ogni risultato corrispondente rappresenta un percorso da un nodo Person quando id è uguale a 2 attraverso un nodo Account connesso utilizzando un arco Owns, in un altro nodo Account utilizzando un arco Transfers.

GRAPH graph_db.FinGraph
MATCH
  (p:Person {id: 2})-[:Owns]->(account:Account)-[t:Transfers]->
  (to_account:Account)
RETURN
  p.id AS sender_id, account.id AS from_id, to_account.id AS to_id;

Il risultato è simile al seguente:

sender_id from_id to_id
2 20 7
2 20 16

Pattern di percorsi quantificati

Un pattern quantificato ripete un pattern all'interno di un intervallo specificato.

Trova un pattern di archi quantificato

Per trovare percorsi di lunghezza variabile, puoi applicare un quantificatore a un pattern di arco. La seguente query lo dimostra trovando gli account di destinazione che distano da uno a tre trasferimenti da un'origine Account con un valore id di 7.

La query applica il quantificatore {1, 3} al pattern di arco -[e:Transfers]->. In questo modo, la query deve trovare i percorsi che ripetono il pattern di archi Transfers una, due o tre volte. La clausola WHERE viene utilizzata per escludere l'account di origine dai risultati. La funzione ARRAY_LENGTH viene utilizzata per accedere alla e group variable.

GRAPH graph_db.FinGraph
MATCH (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account)
WHERE src != dst
RETURN src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length, dst.id AS dst_account_id;

Il risultato è simile al seguente:

src_account_id path_length dst_account_id
7 1 16
7 1 16
7 3 16
7 3 16
7 2 20
7 2 20

Alcune righe dei risultati sono ripetute. Questo perché tra gli stessi nodi di origine e di destinazione possono esistere più percorsi che corrispondono al pattern e la query li restituisce tutti.

Trova un pattern di percorso quantificato

La seguente query trova i percorsi tra i nodi Account con uno o due archi Transfers attraverso account intermedi bloccati.

Il pattern del percorso tra parentesi è quantificato e la relativa clausola WHERE specifica le condizioni per il pattern ripetuto.

GRAPH graph_db.FinGraph
MATCH
  (src:Account)
  ((a:Account)-[:Transfers]->(b:Account {is_blocked:true}) WHERE a != b){1,2}
    -[:Transfers]->(dst:Account)
RETURN src.id AS src_account_id, dst.id AS dst_account_id;

Il risultato è simile al seguente:

src_account_id dst_account_id
7 20
7 20
20 20

Variabili di gruppo

Una variabile di pattern del grafo dichiarata in un pattern quantificato diventa una variabile di gruppo quando vi si accede al di fuori di quel pattern. Quindi, si associa a un array di elementi del grafico corrispondenti.

Puoi accedere a una variabile di gruppo come array. I suoi elementi del grafico vengono conservati nell'ordine in cui vengono visualizzati lungo i percorsi corrispondenti. Puoi aggregare una variabile di gruppo utilizzando l'aggregazione orizzontale.

Variabile del gruppo di accesso

Nell'esempio seguente, l'accesso alla variabile e avviene come segue:

  • Come variabile di pattern del grafo associata a un singolo arco nella clausola WHERE e.amount > 100 quando si trova all'interno del pattern quantificato.
  • Come variabile di gruppo associata a un array di elementi arco in ARRAY_LENGTH(e) nell'istruzione RETURN quando si trova all'esterno del pattern quantificato.
  • Come variabile di gruppo associata a un array di elementi perimetrali, aggregata da SUM(e.amount) all'esterno del pattern quantificato. Questo è un esempio di aggregazione orizzontale.
GRAPH graph_db.FinGraph
MATCH
  (src:Account {id: 7})-[e:Transfers WHERE e.amount > 100]->{0,2}
  (dst:Account)
WHERE src.id != dst.id
LET total_amount = SUM(e.amount)
RETURN
  src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length,
  total_amount, dst.id AS dst_account_id;

Il risultato è simile al seguente:

src_account_id path_length total_amount dst_account_id
7 1 300 16
7 2 600 20

Prefissi di ricerca del percorso

Per limitare i percorsi corrispondenti all'interno di gruppi che condividono nodi di origine e di destinazione, puoi utilizzare il prefisso di ricerca del percorso ANY, ANY SHORTEST o ANY CHEAPEST. Puoi applicare questi prefissi solo prima di un intero pattern di percorso e non puoi applicarli tra parentesi.

Corrispondenza utilizzando ANY

La seguente query trova tutti gli account univoci raggiungibili che si trovano a una o due Transfers di distanza da un determinato nodo Account.

Il prefisso di ricerca del percorso ANY garantisce che la query restituisca un solo percorso tra una coppia univoca di nodi src e dst Account. Nell'esempio seguente, anche se puoi raggiungere il nodo Account con {id: 16} in due percorsi diversi dal nodo Account di origine, la query restituisce un solo percorso.

GRAPH graph_db.FinGraph
MATCH ANY (src:Account {id: 7})-[e:Transfers]->{1,2}(dst:Account)
LET ids_in_path = ARRAY_CONCAT(ARRAY_AGG(e.Id), [dst.Id])
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ids_in_path;

Il risultato è simile al seguente:

src_account_id dst_account_id ids_in_path
7 16 7,16
7 20 7,16,20

Corrispondenza utilizzando ANY SHORTEST

Il prefisso di ricerca del percorso ANY SHORTEST restituisce un singolo percorso per ogni coppia di nodi di origine e di destinazione, selezionati tra quelli con il numero minimo di archi.

Ad esempio, la seguente query trova uno dei percorsi più brevi tra un nodo Account con valore id di 7 e un nodo Account con valore id di 20. La query prende in considerazione i percorsi con un numero di archi Transfers compreso tra uno e tre.

GRAPH graph_db.FinGraph
MATCH ANY SHORTEST (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account {id: 20})
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ARRAY_LENGTH(e) AS path_length;

Il risultato è simile al seguente:

src_account_id dst_account_id path_length
7 20 2

Corrispondenza utilizzando ANY CHEAPEST

Il prefisso di ricerca del percorso ANY CHEAPEST garantisce che, per ogni coppia di account di origine e di destinazione, la query restituisca un solo percorso con il costo di calcolo totale minimo.

La seguente query trova un percorso con il costo di calcolo totale minimo tra i nodi Account. Questo costo si basa sulla somma della proprietà amount degli archi Transfers. La ricerca prende in considerazione i percorsi con un numero di archi Transfers compreso tra uno e tre.

GRAPH graph_db.FinGraph
MATCH ANY CHEAPEST (src:Account)-[e:Transfers COST e.amount]->{1,3}(dst:Account)
LET total_cost = sum(e.amount)
RETURN src.id AS src_account_id, dst.id AS dst_account_id, total_cost;

Il risultato è simile al seguente:

src_account_id dst_account_id total_cost
7 7 900
7 16 100
7 20 400
16 7 800
16 16 500
16 20 300
20 7 500
20 16 200
20 20 500

Pattern di grafi

Un pattern di grafico è costituito da uno o più pattern di percorso, separati da una virgola (,). I pattern di grafico possono contenere una clausola WHERE, che consente di accedere a tutte le variabili del pattern di grafico nei pattern di percorso per formare condizioni di filtro. Ogni pattern di percorso produce una raccolta di percorsi.

Corrispondenza utilizzando un pattern di grafo

La seguente query identifica gli account intermediari e i relativi proprietari coinvolti in transazioni di importo superiore a 200, attraverso le quali i fondi vengono trasferiti da un account di origine a un account bloccato.

I seguenti pattern di percorso formano il pattern del grafo:

  • Il primo pattern trova i percorsi in cui il trasferimento avviene da un account a un account bloccato utilizzando un account intermedio.
  • Il secondo pattern trova i percorsi da un account alla persona proprietaria.

La variabile interm funge da collegamento comune tra i due pattern di percorso, il che richiede che interm faccia riferimento allo stesso nodo elemento in entrambi i pattern di percorso. In questo modo viene creata un'operazione di equi-join basata sulla variabile interm.

GRAPH graph_db.FinGraph
MATCH
  (src:Account)-[t1:Transfers]->(interm:Account)-[t2:Transfers]->(dst:Account),
  (interm)<-[:Owns]-(p:Person)
WHERE dst.is_blocked = TRUE AND t1.amount > 200 AND t2.amount > 200
RETURN
  src.id AS src_account_id, dst.id AS dst_account_id,
  interm.id AS interm_account_id, p.id AS owner_id;

Il risultato è simile al seguente:

src_account_id dst_account_id interm_account_id owner_id
20 16 7 1

Istruzioni di query lineari

Puoi concatenare più istruzioni di grafico per formare un'istruzione di query lineare. Le istruzioni vengono eseguite nello stesso ordine in cui vengono visualizzate nella query.

  • Ogni istruzione prende come input l'output dell'istruzione precedente. L'input è vuoto per la prima istruzione.

  • L'output dell'ultima istruzione è il risultato finale.

Ad esempio, puoi utilizzare istruzioni di query lineari per trovare il trasferimento massimo a un account bloccato. La seguente query trova l'account e il suo proprietario con il trasferimento in uscita più grande verso un account bloccato.

GRAPH graph_db.FinGraph
MATCH (src_account:Account)-[transfer:Transfers]->(dst_account:Account {is_blocked:true})
ORDER BY transfer.amount DESC
LIMIT 1
MATCH (src_account:Account)<-[owns:Owns]-(owner:Person)
RETURN src_account.id AS account_id, owner.name AS owner_name;

La tabella seguente illustra questo processo mostrando i risultati intermedi passati tra ogni istruzione. Per brevità, vengono mostrate solo alcune proprietà.

Affermazione Risultato intermedio (abbreviato)
MATCH
  (src_account:Account)
    -[transfer:Transfers]->
  (dst_account:Account {is_blocked:true})
src_account trasferimento dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}
{id: 7} {amount: 100.0} {id: 16, is_blocked: true}
{id: 20} {amount: 200.0} {id: 16, is_blocked: true}

ORDER BY transfer.amount DESC
src_account trasferimento dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}
{id: 20} {amount: 200.0} {id: 16, is_blocked: true}
{id: 7} {amount: 100.0} {id: 16, is_blocked: true}

LIMIT 1
src_account trasferimento dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}

MATCH
  (src_account:Account)
    <-[owns:Owns]-
  (owner:Person)
src_account trasferimento dst_account owns owner
{id: 7} {amount: 300.0} {id: 16, is_blocked: true} {person_id: 1, account_id: 7} {id: 1, name: Alex}
RETURN
  src_account.id AS account_id,
  owner.name AS owner_name
        
account_id owner_name
7 Alex

Il risultato è simile al seguente:

account_id owner_name
7 Alex

Dichiarazione return

L'istruzione RETURN specifica cosa restituire dai pattern corrispondenti. Può accedere alle variabili dei pattern dei grafi e includere espressioni e altre clausole, come ORDER BY e GROUP BY.

BigQuery Graph non supporta la restituzione di elementi del grafo come risultati delle query. Per restituire l'intero elemento del grafico, utilizza la funzione TO_JSON.

Restituisci gli elementi del grafico come JSON

GRAPH graph_db.FinGraph
MATCH (n:Account {id: 7})
-- Returning a graph element in the final results is NOT allowed. Instead, use
-- the TO_JSON function or explicitly return the graph element's properties.
RETURN TO_JSON(n) AS n;

Il risultato è simile al seguente:

n
{"identifier":"mUZpbkdyYXBoLkFjY291bnQAeJEO","kind":"node","labels":["Account"],"properties":{"create_time":"2020-01-10T14:22:20.222Z","id":7,"is_blocked":false,"nick_name":"Vacation Fund"}}

Crea query più grandi con la parola chiave NEXT

Puoi concatenare più istruzioni di query lineare del grafico utilizzando la parola chiave NEXT. La prima istruzione riceve un input vuoto e l'output di ogni istruzione successiva diventa l'input per quella successiva.

L'esempio seguente trova il proprietario dell'account con il maggior numero di trasferimenti in entrata concatenando più istruzioni lineari del grafo. Puoi utilizzare la stessa variabile, ad esempio account, per fare riferimento allo stesso elemento del grafico in più istruzioni lineari.

GRAPH graph_db.FinGraph
MATCH (:Account)-[:Transfers]->(account:Account)
RETURN account, COUNT(*) AS num_incoming_transfers
GROUP BY account
ORDER BY num_incoming_transfers DESC
LIMIT 1

NEXT

MATCH (account:Account)<-[:Owns]-(owner:Person)
RETURN account.id AS account_id, owner.name AS owner_name, num_incoming_transfers;

Il risultato è simile al seguente:

account_id owner_name num_incoming_transfers
16 Lee 3

Puoi anche combinare istruzioni di query lineari con operatori di set.

Funzioni ed espressioni

Nelle query sui grafi puoi utilizzare tutte le funzioni GoogleSQL (sia le funzioni aggregate che quelle scalari), gli operatori e le espressioni condizionali. BigQuery Graph supporta anche funzioni GQL e operatori GQL che possono essere utilizzati solo nelle query dei grafi.

La seguente query include una combinazione di funzioni e operatori GQL e SQL all'interno di una query del grafo:

GRAPH graph_db.FinGraph
MATCH (person:Person)-[o:Owns]->(account:Account)
WHERE person IS SOURCE OF o
RETURN person, ARRAY_AGG(account.nick_name) AS accounts
GROUP BY person

NEXT

RETURN
  LABELS(person) AS labels,
  accounts,
  CONCAT(person.city, ", ", person.country) AS location,
  TO_JSON(person) AS person
LIMIT 1;

Il risultato è simile al seguente:

etichette account località persona
Person ["Vacation Fund"] Adelaide, Australia {"identifier":"mUZpbkdyYXBoLlBlcnNvbgB4kQI=","kind":"node","labels":["Person"],"properties":{"birthday":"1991-12-21T08:00:00Z","city":"Adelaide","country":"Australia","id":1,"name":"Alex"}}

Sottoquery

Una subquery è una query nidificata in un'altra query. Le seguenti regole si applicano alle sottoquery all'interno delle query del grafo:

  • Una subquery è racchiusa tra parentesi graffe {}.
  • Una sottoquery inizia con una clausola GRAPH per specificare il grafico nell'ambito. Il grafo specificato non deve essere lo stesso utilizzato nella query esterna.
  • Una variabile del pattern del grafico dichiarata al di fuori dell'ambito della sottoquery non può essere dichiarata di nuovo all'interno della sottoquery, ma può essere richiamata in espressioni o funzioni all'interno della sottoquery.

Utilizza una sottoquery per trovare il numero totale di trasferimenti da ogni account

La seguente query illustra l'utilizzo della subquery VALUE. La subquery è racchiusa tra parentesi graffe {} precedute dalla parola chiave VALUE. La query restituisce il numero totale di trasferimenti avviati da un account.

GRAPH graph_db.FinGraph
MATCH (p:Person)-[:Owns]->(account:Account)
RETURN p.name, account.id AS account_id, VALUE {
  GRAPH graph_db.FinGraph
  MATCH (a:Account)-[transfer:Transfers]->(:Account)
  WHERE a = account
  RETURN COUNT(transfer) AS num_transfers
} AS num_transfers;

Il risultato è simile al seguente:

nome account_id num_transfers
Alex 7 2
Dana 20 2
Lee 16 1

Per un elenco delle espressioni di subquery supportate, consulta Subquery di BigQuery Graph.

Parametri di query

Puoi eseguire query su BigQuery Graph con parametri. Per saperne di più, consulta la sintassi e scopri come eseguire query parametrizzate.

La seguente query corrisponde ai nodi Person che hanno un valore id corrispondente a un parametro di query:

GRAPH graph_db.FinGraph
MATCH (person:Person {id: @id})
RETURN person.name;

Esegui query su grafici e tabelle insieme

Puoi combinare query sui grafi e query SQL utilizzando l'operatore GRAPH_TABLE.

L'operatore GRAPH_TABLE accetta una query di grafo lineare e restituisce il risultato in un formato tabulare che può essere integrato in una query SQL. Questa interoperabilità ti consente di arricchire i risultati delle query sui grafici con contenuti non relativi ai grafici e viceversa.

Ad esempio, puoi creare una tabella CreditReports e inserire alcuni report di credito, come mostrato nell'esempio seguente:

CREATE TABLE graph_db.CreditReports (
  person_id     INT64 NOT NULL,
  create_time   TIMESTAMP NOT NULL,
  score         INT64 NOT NULL,
  PRIMARY KEY (person_id, create_time) NOT ENFORCED
);
INSERT INTO graph_db.CreditReports (person_id, create_time, score)
VALUES
  (1,"2020-01-10 06:22:20.222", 700),
  (2,"2020-02-10 06:22:20.222", 800),
  (3,"2020-03-10 06:22:20.222", 750);

Successivamente, puoi identificare persone specifiche tramite la corrispondenza dei pattern del grafo in GRAPH_TABLE e unire i risultati della query del grafo alla tabella CreditReports per recuperare i punteggi di affidabilità creditizia.

SELECT
  gt.person.id,
  credit.score AS latest_credit_score
FROM GRAPH_TABLE(
  graph_db.FinGraph
  MATCH (person:Person)-[:Owns]->(:Account)-[:Transfers]->(account:Account {is_blocked:true})
  RETURN DISTINCT person
) AS gt
JOIN graph_db.CreditReports AS credit
  ON gt.person.id = credit.person_id
ORDER BY credit.create_time;

Il risultato è simile al seguente:

person_id latest_credit_score
1 700
2 800

Passaggi successivi