Passa al contenuto principale

SQL diventa più facile: annunciata la nuova sintassi Pipe

Rendi SQL più semplice e potente esprimendo tutte le trasformazioni in ordine

SQL Gets Easier: Announcing New Pipe Syntax

Pubblicato: 30 aprile 2025

Ingegneria9 min di lettura

Summary

  • SQL ha successo perché il linguaggio dichiara quali dati dovrebbero uscire da ogni query senza specificare esattamente come il motore dovrebbe eseguirla.
  • Tuttavia, SQL può diventare confusionario per i nuovi utenti da imparare e per gli utenti esistenti da mantenere, specialmente in presenza di molte sottoquery annidate.
  • Qui annunciamo una nuova sintassi per aiutare in questo, consentendo agli utenti di comporre la logica SQL come una sequenza di clausole indipendenti disposte in qualsiasi ordine, molto simili ai DataFrame.

SQL è la lingua franca per l'analisi dei dati strutturati da diversi decenni, e negli ultimi anni abbiamo lavorato molto per supportare ANSI SQL e le varie estensioni per rendere SQL più piacevole da usare su Databricks. Oggi, siamo entusiasti di annunciare la sintassi pipe SQL, la più grande estensione che abbiamo fatto negli ultimi anni per rendere SQL drasticamente più facile da scrivere e capire, in modo completamente retrocompatibile.

Una delle sfide chiave in SQL stesso finora risiede nell'ordinamento della "logica". Quando si scrive una query, molti autori pensano in termini dei seguenti passaggi logici: identificare l'elenco delle tabelle da interrogare, unirle, filtrare le righe indesiderate e, infine, aggregare. Questo ordinamento logico può essere espresso nel modo seguente:

La query SQL per questi passaggi sarebbe la seguente:

Invece di scrivere i passaggi in ordine (1, 2, 3) dobbiamo invece scriverli nell'ordine (3, 2, 1). Questo è confusionario e il problema si aggrava solo quando aggiungiamo più logica e passaggi a ciascuna query.

DataFrames e le persone che li amano

Al contrario, pensiamo ai DataFrames. Una grande fonte della popolarità originale di Apache Spark tra i data scientist è la potente capacità delle sue API DataFrame Scala e Python. I programmi possono applicarle per esprimere la loro logica in un ordinamento naturale dei passaggi. Partendo dalla tabella sorgente, gli utenti possono concatenare operazioni indipendenti e componibili una dopo l'altra, rendendo più facile costruire trasformazioni di dati complesse in una sequenza chiara e intuitiva.

Questo design promuove la leggibilità e semplifica il debug mantenendo la flessibilità. È una delle ragioni principali per cui Databricks ha ottenuto la sua massiccia crescita nel settore finora nello spazio della gestione dei dati, e questo slancio continua solo ad aumentare oggi.

Ecco come appare la stessa logica nei DataFrames PySpark:

Questo approccio supporta un'iterazione flessibile sulle idee. Sappiamo che i dati sorgente esistono in qualche file, quindi possiamo iniziare subito creando un DataFrame che rappresenta quei dati come una relazione. Dopo aver pensato un po', ci rendiamo conto che vogliamo filtrare le righe in base alla colonna stringa. OK, quindi possiamo aggiungere un passaggio .filter alla fine del DataFrame precedente. Oh, e vogliamo calcolare una proiezione alla fine, quindi la aggiungiamo alla fine della sequenza.

Molti di questi utenti desiderano che SQL si comporti in modo più simile ai linguaggi di dati moderni come questo. Storicamente, ciò non era possibile e gli utenti dovevano scegliere un modo di pensare o l'altro.

Introduzione della nuova sintassi pipe SQL!

Avanti veloce a oggi: ora è possibile avere il meglio di entrambi i mondi! La sintassi pipe rende SQL sia più facile da scrivere che da leggere ed estendere in seguito, e ci libera da questa confusione permettendoci di usare semplicemente gli stessi passaggi nell'ordine in cui li abbiamo pensati.

Alla conferenza VLDB 2024, Google ha pubblicato un paper industriale che propone questo come nuovo standard. Gli ingegneri di elaborazione delle query hanno implementato questa funzionalità e l'hanno abilitata per impostazione predefinita in Apache Spark 4.0 (documentazione) e Databricks Runtime 16.2 (documentazione) e versioni successive. È retrocompatibile con la sintassi SQL normale: gli utenti possono scrivere intere query utilizzando questa sintassi, solo determinate sottoquery o qualsiasi combinazione utile.

Il paper industriale fornisce la query 13 dal benchmark TPC-H come primo esempio:

Utilizzando la sintassi pipe per esprimere la stessa logica, applichiamo gli operatori in sequenza dall'inizio alla fine con qualsiasi ordinamento arbitrario:

E come funzionano le aggregazioni?

Con SQL normale, quando vogliamo raccogliere righe in gruppi in base ai valori di colonne o espressioni, aggiungiamo una clausola GROUP BY alla fine della query SQL in costruzione. Le aggregazioni da eseguire rimangono bloccate in cima alla lista SELECT all'inizio della query e ogni espressione deve ora essere:

  • Una chiave di raggruppamento, nel qual caso la clausola GROUP BY deve contenere una copia dell'espressione (o un riferimento alias o ordinale).
  • Una funzione di aggregazione come SUM, COUNT, MIN o MAX, che accetta un'espressione basata su colonne della tabella di input come SUM(A + B). Possiamo anche calcolare proiezioni sul risultato, come SUM(A) + 1.

Qualsiasi elemento SELECT che non soddisfa una di queste categorie genererà un errore come "espressione X è apparsa nella lista SELECT ma non è stata raggruppata o aggregata".

Anche le regole della clausola WHERE cambiano:

  • Se appare prima della clausola GROUP BY, allora filtriamo le righe secondo i criteri specificati prima di aggregarle.
  • Altrimenti, la query non è valida e otteniamo un errore strano. L'utente deve invece scrivere una clausola HAVING con la stessa condizione di filtro e deve apparire solo dopo la clausola GROUP BY, ma non prima.
  • La clausola QUALIFY serve anche come altro esempio della necessità di comprendere e utilizzare una sintassi separata per eseguire il filtraggio a seconda del contesto.

La sintassi pipe risolve questo problema separando ogni operazione di aggregazione (con possibile raggruppamento) in un passaggio dedicato che può essere applicato in qualsiasi momento. Solo le espressioni con funzioni di aggregazione all'interno possono apparire in questo passaggio, e le funzioni di aggregazione non possono apparire nei passaggi |> SELECT. Se l'autore SQL dimentica uno qualsiasi di questi invarianti, i messaggi di errore risultanti sono molto chiari e facili da capire.

Inoltre, non è più necessario ripetere le espressioni di raggruppamento, poiché possiamo scriverle in un'unica clausola GROUP BY.

Guardiamo l'esempio precedente con un'aggregazione aggiunta alla fine, che restituisce una tabella di risultati con due colonne L, M:

eBook

Introduzione all'ETL

Divertimento con le sottoquery

SQL normale generalmente richiede che le clausole appaiano in un ordine specifico, senza ripetizioni. Se vogliamo applicare ulteriori operazioni al risultato di una query SQL, il modo per farlo è utilizzare una sottoquery tabellare in cui racchiudiamo la query originale tra parentesi e la utilizziamo nella clausola FROM di una query racchiusa. La query all'inizio di questo post mostra un semplice esempio di ciò.

Si noti che questa nidificazione può avvenire un numero arbitrario di volte. Ad esempio, ecco la query 23 di TPC-DS:

Sta diventando confusionario e difficile da leggere con tutti i livelli di parentesi e indentazione!

Dall'altra parte, con la sintassi pipe di SQL non c'è bisogno di subquery di tabelle. Poiché gli operatori pipe possono apparire in qualsiasi ordine, possiamo semplicemente aggiungerne di nuovi alla fine in qualsiasi momento, e tutti i passaggi funzionano ancora allo stesso modo.

Inizia facilmente con la retrocompatibilità

La sintassi pipe rielabora il modo in cui gli autori scrivono, leggono ed estendono SQL. Potrebbe sembrare una sfida passare dal modo di pensare di SQL regolare a questo nuovo paradigma. Potresti persino avere un ampio corpo di query SQL esistenti scritte in precedenza di cui sei responsabile della manutenzione e della possibile estensione futura. Come possiamo far funzionare questo con due sintassi SQL?

Fortunatamente, questo non è un problema con la nostra nuova sintassi SQL. È completamente interoperabile con SQL regolare, dove qualsiasi query (o subquery di tabella) può apparire utilizzando una delle due sintassi. Possiamo iniziare a scrivere nuove query utilizzando la sintassi pipe di SQL e mantenere le nostre precedenti se necessario. Possiamo persino iniziare a sostituire le subquery di tabelle delle nostre query precedenti con la nuova sintassi e mantenere tutto il resto uguale, come aggiornare solo una parte di TPC-H Q13 dall'inizio di questo post:

Poiché gli operatori pipe di SQL possono seguire qualsiasi query valida, è anche possibile iniziare ad aggiungerli a query SQL regolari esistenti. Ad esempio:

Inizia subito!

La sintassi pipe di SQL è pronta per essere provata in Databricks Runtime versione 16.2 e successive. Oppure scarica Apache Spark 4.0 e provala nel mondo open source. La sintassi è conforme al paper industriale Pipe Syntax in SQL, quindi la nuova sintassi sarà portabile con Google BigQuery così come con il progetto open source ZetaSQL.

Questa sintassi sta anche iniziando a generare interesse nella community e ad apparire altrove, aumentando la portabilità ora e nel tempo.

Provala e sperimenta i vantaggi di rendere le query SQL più semplici da scrivere per utenti nuovi ed esperti, e rendi la leggibilità e l'estensibilità future più facili riducendo l'incidenza di subquery complesse a favore di operatori chiari e componibili.

(Questo post sul blog è stato tradotto utilizzando strumenti basati sull'intelligenza artificiale) Post originale

Non perdere mai un post di Databricks

Iscriviti al nostro blog e ricevi gli ultimi post direttamente nella tua casella di posta elettronica.