SQL
Funciones de ventana
Buscar..
Sumando las filas totales seleccionadas a cada fila
SELECT your_columns, COUNT(*) OVER() as Ttl_Rows FROM your_data_set
carné de identidad | nombre | Ttl_Rows |
---|---|---|
1 | ejemplo | 5 |
2 | foo | 5 |
3 | bar | 5 |
4 | baz | 5 |
5 | quux | 5 |
En lugar de usar dos consultas para obtener un recuento y luego la línea, puede usar un agregado como función de ventana y usar el conjunto de resultados completo como ventana.
Esto se puede usar como base para cálculos adicionales sin la complejidad de uniones adicionales.
Configuración de una bandera si otras filas tienen una propiedad común
Digamos que tengo estos datos:
Articulos de mesa
carné de identidad | nombre | etiqueta |
---|---|---|
1 | ejemplo | unique_tag |
2 | foo | sencillo |
42 | bar | sencillo |
3 | baz | Hola |
51 | quux | mundo |
Me gustaría obtener todas esas líneas y saber si una etiqueta es utilizada por otras líneas
SELECT id, name, tag, COUNT(*) OVER (PARTITION BY tag) > 1 AS flag FROM items
El resultado será:
carné de identidad | nombre | etiqueta | bandera |
---|---|---|---|
1 | ejemplo | unique_tag | falso |
2 | foo | sencillo | cierto |
42 | bar | sencillo | cierto |
3 | baz | Hola | falso |
51 | quux | mundo | falso |
En caso de que su base de datos no tenga OVER y PARTITION, puede usar esto para producir el mismo resultado:
SELECT id, name, tag, (SELECT COUNT(tag) FROM items B WHERE tag = A.tag) > 1 AS flag FROM items A
Obtener un total acumulado
Teniendo en cuenta estos datos:
fecha | cantidad |
---|---|
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
Te regalaré
fecha | cantidad | corriendo |
---|---|---|
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 |
Obtención de las N filas más recientes sobre agrupación múltiple
Dados estos datos
ID_usuario | Fecha de Terminación |
---|---|
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, obtendrás la fila más reciente por user_id
:
ID_usuario | Fecha de Terminación | Row_Num |
---|---|---|
1 | 2016-07-21 | 1 |
2 | 2016-07-22 | 1 |
Búsqueda de registros "fuera de secuencia" mediante la función LAG ()
Dados estos datos de muestra:
CARNÉ DE IDENTIDAD | ESTADO | STATUS_TIME | STATUS_BY |
---|---|---|---|
1 | UNO | 2016-09-28-19.47.52.501398 | USER_1 |
3 | UNO | 2016-09-28-19.47.52.501511 | USER_2 |
1 | TRES | 2016-09-28-19.47.52.501517 | USER_3 |
3 | DOS | 2016-09-28-19.47.52.501521 | USER_2 |
3 | TRES | 2016-09-28-19.47.52.501524 | USER_4 |
Los elementos identificados por los valores de ID
deben pasar de STATUS
"UNO" a "DOS" a "TRES" en secuencia, sin saltarse estados. El problema es encontrar los valores de los usuarios ( STATUS_BY
) que infringen la regla y pasar de "UNO" inmediatamente a "TRES".
La función analítica LAG()
ayuda a resolver el problema devolviendo a cada fila el valor en la fila anterior:
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'
En caso de que su base de datos no tenga LAG (), puede usar esto para producir el mismo resultado:
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'