Funciones de ventana#

  • Ultima modificación: Mar 6, 2024 | YouTube

Preparación

[1]:
import sqlite3

from IPython.core.magic import register_cell_magic, register_line_magic

conn = sqlite3.connect(":memory:")
cur = conn.cursor()


@register_line_magic
def sql(line):
    return cur.execute(line).fetchall()


@register_cell_magic
def sqlite3(line, cell):
    cell = [
        l for l in cell.split("\n") if l[0:2] != "--" and l[0:2] not in ["--", "##"]
    ]
    cell = "\n".join(cell)
    return cur.execute(cell).fetchall()


@register_cell_magic
def sqlite3script(line, cell):
    cell = [l for l in cell.split("\n") if len(l) >= 2 and l[0:2] not in ["--", "##"]]
    cell = "\n".join(cell)
    conn.executescript(cell)
    conn.commit()

Datos

[2]:
%%sqlite3script

DROP TABLE IF EXISTS t1;

CREATE TABLE t1(
    a INTEGER PRIMARY KEY,
    b,
    c
);

INSERT INTO
    t1
VALUES
    (1, 'G', 'one'  ),
    (2, 'F', 'two'  ),
    (3, 'E', 'three'),
    (4, 'D', 'one'  ),
    (5, 'C', 'two'  ),
    (6, 'B', 'three'),
    (7, 'A', 'one'  );

Conceptos fundamentales

  • Son funciones SQL cuyas entradas son tomadas de una “ventana” conformada por una o más filas en los resultados de una clausula SELECT.

  • Se distingen de otras funciones SQL porque usan la palabra reservada OVER.

  • Las funciones de ventana también pueden tener una clausula FILTER entre la función y la clausula OVER.

  • No pueden usar DISTINCT

  • Las funciones de agregación no cambian el número de filas retornadas y agregan a cada fila el resultado de la función de agregación.

[3]:
%%sqlite3

SELECT
    a, b, c, max(a)
OVER
(
    PARTITION BY c
)
FROM
    t1;
[3]:
[(1, 'G', 'one', 7),
 (4, 'D', 'one', 7),
 (7, 'A', 'one', 7),
 (3, 'E', 'three', 6),
 (6, 'B', 'three', 6),
 (2, 'F', 'two', 5),
 (5, 'C', 'two', 5)]
[4]:
%%sqlite3

SELECT
    a, b, c, rank()
OVER
(
    PARTITION BY c
    ORDER BY b
)
FROM
    t1;
[4]:
[(7, 'A', 'one', 1),
 (4, 'D', 'one', 2),
 (1, 'G', 'one', 3),
 (6, 'B', 'three', 1),
 (3, 'E', 'three', 2),
 (5, 'C', 'two', 1),
 (2, 'F', 'two', 2)]
[6]:
%%sqlite3

SELECT
    a, b, group_concat(b, '.')
OVER
(
    ORDER BY
        a
    ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
)
AS
    group_concat
FROM
    t1;
[6]:
[(1, 'G', 'G.F'),
 (2, 'F', 'G.F.E'),
 (3, 'E', 'F.E.D'),
 (4, 'D', 'E.D.C'),
 (5, 'C', 'D.C.B'),
 (6, 'B', 'C.B.A'),
 (7, 'A', 'B.A')]
  • La clausula PARTITION BY permite dividir el resultado de la consulta en una o más particiones. Una partición esta conformada por todas las filas que tienen el mismo valor para todos los terminos de la clausula PARTITION BY.

[7]:
%%sqlite3

SELECT
    c, a, b, group_concat(b, '.')
OVER
(
    PARTITION BY c
    ORDER BY a
    RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
)
AS
    group_concat
FROM
    t1
ORDER BY
    c, a;
[7]:
[('one', 1, 'G', 'G.D.A'),
 ('one', 4, 'D', 'D.A'),
 ('one', 7, 'A', 'A'),
 ('three', 3, 'E', 'E.B'),
 ('three', 6, 'B', 'B'),
 ('two', 2, 'F', 'F.C'),
 ('two', 5, 'C', 'C')]
[8]:
%%sqlite3

SELECT
    c, a, b, group_concat(b, '.')
OVER
(
    PARTITION BY c
    ORDER BY a
    RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
)
AS
    group_concat
FROM
    t1
ORDER BY
    a;
[8]:
[('one', 1, 'G', 'G.D.A'),
 ('two', 2, 'F', 'F.C'),
 ('three', 3, 'E', 'E.B'),
 ('one', 4, 'D', 'D.A'),
 ('two', 5, 'C', 'C'),
 ('three', 6, 'B', 'B'),
 ('one', 7, 'A', 'A')]
[9]:
%%sqlite3

SELECT
    a, b, c, group_concat(b, '.')
OVER
(
    ORDER BY c
)
AS
    group_concat
FROM
    t1
ORDER BY
    c;
[9]:
[(1, 'G', 'one', 'G.D.A'),
 (4, 'D', 'one', 'G.D.A'),
 (7, 'A', 'one', 'G.D.A'),
 (3, 'E', 'three', 'G.D.A.E.B'),
 (6, 'B', 'three', 'G.D.A.E.B'),
 (2, 'F', 'two', 'G.D.A.E.B.F.C'),
 (5, 'C', 'two', 'G.D.A.E.B.F.C')]
[10]:
%%sqlite3

SELECT
    c, a, b, group_concat(b, '.')
OVER
(
    ORDER BY c, a
    ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
)
AS
    group_concat
FROM
    t1
ORDER BY
    c, a;
[10]:
[('one', 1, 'G', 'G.D.A.E.B.F.C'),
 ('one', 4, 'D', 'D.A.E.B.F.C'),
 ('one', 7, 'A', 'A.E.B.F.C'),
 ('three', 3, 'E', 'E.B.F.C'),
 ('three', 6, 'B', 'B.F.C'),
 ('two', 2, 'F', 'F.C'),
 ('two', 5, 'C', 'C')]
[11]:
%%sqlite3

SELECT
    c, a, b, group_concat(b, '.')
FILTER
(
    WHERE c!='two'
)
OVER
(
  ORDER BY a
)
AS
    group_concat
FROM
    t1
ORDER BY
    a;
[11]:
[('one', 1, 'G', 'G'),
 ('two', 2, 'F', 'G'),
 ('three', 3, 'E', 'G.E'),
 ('one', 4, 'D', 'G.E.D'),
 ('two', 5, 'C', 'G.E.D'),
 ('three', 6, 'B', 'G.E.D.B'),
 ('one', 7, 'A', 'G.E.D.B.A')]