sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo usar una estructura de datos de anillo en funciones de ventana

  • Usar COALESCE como lo proporcionó @Justin.
  • Con first_value() / last_value() usted necesita para agregar un ORDER BY cláusula a la definición de la ventana o el orden es indefinido . Simplemente tuviste suerte en el ejemplo, porque las filas están en orden justo después de crear la tabla ficticia.
    Una vez que agregas ORDER BY , el marco de ventana predeterminado termina en la fila actual , y necesita un caso especial del last_value() llamar - o revertir el orden de clasificación en el marco de la ventana como se muestra en mi primer ejemplo.

  • Al reutilizar una definición de ventana varias veces, una WINDOW explícita cláusula simplifica mucho la sintaxis:

SELECT ring, part, ARRAY[
          coalesce(
             lag(part) OVER w
            ,first_value(part) OVER (PARTITION BY ring ORDER BY part DESC))
         ,part
         ,coalesce(
             lead(part) OVER w
            ,first_value(part) OVER w)
         ] AS neighbours
FROM   rp
WINDOW w AS (PARTITION BY ring ORDER BY part);

Mejor aún , reutilice la misma definición de ventana, para que Postgres pueda calcular todos los valores en un solo escaneo. Para que esto funcione, necesitamos definir un marco de ventana personalizado :

SELECT ring, part, ARRAY[
          coalesce(
             lag(part) OVER w
            ,last_value(part) OVER w)
         ,part
         ,coalesce(
             lead(part) OVER w
            ,first_value(part) OVER w)
         ] AS neighbours
FROM   rp
WINDOW w AS (PARTITION BY ring
             ORDER BY part
             RANGE BETWEEN UNBOUNDED PRECEDING
                       AND UNBOUNDED FOLLOWING)
ORDER  BY 1,2;

Incluso puede adaptar la definición del marco para cada llamada de función de ventana:

SELECT ring, part, ARRAY[
          coalesce(
             lag(part) OVER w
            ,last_value(part) OVER (w RANGE BETWEEN CURRENT ROW
                                                AND UNBOUNDED FOLLOWING))
         ,part
         ,coalesce(
             lead(part) OVER w
            ,first_value(part) OVER w)
         ] AS neighbours
FROM   rp
WINDOW w AS (PARTITION BY ring ORDER BY part)
ORDER  BY 1,2;

Podría ser más rápido para anillos con muchas partes. Tendrás que probar.

Violín SQL demostrando los tres con un caso de prueba mejorado. Considere los planes de consulta.

Más sobre definiciones de marcos de ventana:

  • En el manual.
  • Función de ventana de PostgreSQL:partición por comparación
  • Consulta de PostgreSQL con fecha máxima y mínima más identificación asociada por fila