SQL
Funzioni della finestra
Ricerca…
Aggiungere le righe totali selezionate a ogni riga
SELECT your_columns, COUNT(*) OVER() as Ttl_Rows FROM your_data_set
id | nome | Ttl_Rows |
---|---|---|
1 | esempio | 5 |
2 | foo | 5 |
3 | bar | 5 |
4 | baz | 5 |
5 | quux | 5 |
Invece di utilizzare due query per ottenere un conteggio della riga, è possibile utilizzare una funzione di aggregazione come finestra e utilizzare il set di risultati completo come finestra.
Questo può essere usato come base per ulteriori calcoli senza la complessità degli extra self join.
Impostazione di un flag se altre righe hanno una proprietà comune
Diciamo che ho questi dati:
Articoli da tavola
id | nome | etichetta |
---|---|---|
1 | esempio | unique_tag |
2 | foo | semplice |
42 | bar | semplice |
3 | baz | Ciao |
51 | quux | mondo |
Mi piacerebbe avere tutte quelle righe e sapere se un tag è usato da altre linee
SELECT id, name, tag, COUNT(*) OVER (PARTITION BY tag) > 1 AS flag FROM items
Il risultato sarà:
id | nome | etichetta | bandiera |
---|---|---|---|
1 | esempio | unique_tag | falso |
2 | foo | semplice | vero |
42 | bar | semplice | vero |
3 | baz | Ciao | falso |
51 | quux | mondo | falso |
Nel caso in cui il tuo database non abbia OVER e PARTITION puoi usarlo per produrre lo stesso risultato:
SELECT id, name, tag, (SELECT COUNT(tag) FROM items B WHERE tag = A.tag) > 1 AS flag FROM items A
Ottenere un totale parziale
Dati questi dati:
Data | quantità |
---|---|
2016/03/12 | 200 |
2016/03/11 | -50 |
2016/03/14 | 100 |
2016/03/15 | 100 |
2016/03/10 | -250 |
SELECT date, amount, SUM(amount) OVER (ORDER BY date ASC) AS running
FROM operations
ORDER BY date ASC
ti darò
Data | quantità | in esecuzione |
---|---|---|
2016/03/10 | -250 | -250 |
2016/03/11 | -50 | -300 |
2016/03/12 | 200 | -100 |
2016/03/14 | 100 | 0 |
2016/03/15 | 100 | -100 |
Ottenere le N righe più recenti su più raggruppamenti
Dati questi dati
ID utente | Data di completamento |
---|---|
1 | 2016/07/20 |
1 | 2016/07/21 |
2 | 2016/07/20 |
2 | 2016/07/21 |
2 | 2016/07/22 |
;with CTE as
(SELECT *,
ROW_NUMBER() OVER (PARTITION BY User_ID
ORDER BY Completion_Date DESC) Row_Num
FROM Data)
SELECT * FORM CTE WHERE Row_Num <= n
Usando n = 1, otterrai la riga più recente per user_id
:
ID utente | Data di completamento | row_num |
---|---|---|
1 | 2016/07/21 | 1 |
2 | 2016/07/22 | 1 |
Ricerca di record "fuori sequenza" utilizzando la funzione LAG ()
Dati questi dati di esempio:
ID | STATO | STATUS_TIME | STATUS_BY |
---|---|---|---|
1 | UNO | 2016-09-28-19.47.52.501398 | USER_1 |
3 | UNO | 2016-09-28-19.47.52.501511 | Utente_2 |
1 | TRE | 2016-09-28-19.47.52.501517 | Utente_3 |
3 | DUE | 2016-09-28-19.47.52.501521 | Utente_2 |
3 | TRE | 2016-09-28-19.47.52.501524 | USER_4 |
Gli articoli identificati dai valori ID
devono passare da STATUS
'UNO' a 'DUE' a 'TRE' in sequenza, senza saltare gli stati. Il problema è trovare i valori degli utenti ( STATUS_BY
) che violano la regola e passare da "UNO" immediatamente a "TRE".
La funzione analitica di LAG()
aiuta a risolvere il problema restituendo per ogni riga il valore nella riga precedente:
SELECT * FROM (
SELECT
t.*,
LAG(status) OVER (PARTITION BY id ORDER BY status_time) AS prev_status
FROM test t
) t1 WHERE status = 'THREE' AND prev_status != 'TWO'
Nel caso in cui il tuo database non abbia il LAG () puoi usarlo per produrre lo stesso risultato:
SELECT A.id, A.status, B.status as prev_status, A.status_time, B.status_time as prev_status_time
FROM Data A, Data B
WHERE A.id = B.id
AND B.status_time = (SELECT MAX(status_time) FROM Data where status_time < A.status_time and id = A.id)
AND A.status = 'THREE' AND NOT B.status = 'TWO'