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

Unión izquierda con nombre de tabla dinámica derivado de la columna

De cualquier manera, necesita SQL dinámico.

Nombre de tabla como parámetro dado

CREATE OR REPLACE FUNCTION foo(_number int)
  RETURNS TABLE (cpa int, nr text, vym text) AS  -- adapt to actual data types!
$func$
BEGIN
   RETURN QUERY EXECUTE format(
      'SELECT t.cpa, substring(t.ku,'[0-9]+'), p.vym 
       FROM   public."table_data_C" t
       LEFT   JOIN %s p USING (cpa)'
     , 'pa' || _number
     );
END
$func$ LANGUAGE plpgsql;

Llamar:

SELECT * FROM foo(456887)

En general, desinfectaría los nombres de las tablas con format ( %I ) para evitar la inyección SQL. Con solo un integer como entrada dinámica que no es necesaria. Más detalles y enlaces en esta respuesta relacionada:
INSERTAR con el nombre de la tabla dinámica en la función de activación

Modelo de datos

Puede haber buenas razones para el modelo de datos. Como partición/fragmentación o privilegios separados...
Si no tiene una razón tan buena, considere consolidar varias tablas con un esquema idéntico en una sola y agregue el number como columna. Entonces no necesita SQL dinámico.

Considere herencia . Luego puede agregar una condición en tableoid para recuperar solo filas de una tabla secundaria dada:

SELECT * FROM parent_table
WHERE  tableoid = 'pa456887'::regclass

Sin embargo, tenga en cuenta las limitaciones de la herencia. Respuestas relacionadas:

Nombre de la segunda tabla según el valor de la primera

Derivar el nombre de la tabla de combinación a partir de los valores de la primera tabla complica las cosas dinámicamente.

Solo para unas pocas mesas

LEFT JOIN cada uno en tableoid . Solo hay una coincidencia por fila, así que use COALESCE .

SELECT t.*, t.tbl, COALESCE(p1.vym, p2.vym, p3.vym) AS vym
FROM  (
   SELECT cpa, ('pa' || substring(ku,'[0-9]+'))::regclass AS tbl
   FROM   public."table_data_C"
   -- WHERE <some condition>
   ) t
LEFT   JOIN pa456887 p1 ON p1.cpa = t.cpa AND p1.tableoid = t.tbl
LEFT   JOIN pa456888 p2 ON p2.cpa = t.cpa AND p2.tableoid = t.tbl
LEFT   JOIN pa456889 p3 ON p3.cpa = t.cpa AND p3.tableoid = t.tbl

Para muchas mesas

Combine un bucle con consultas dinámicas:

CREATE OR REPLACE FUNCTION foo(_number int)
  RETURNS TABLE (cpa int, nr text, vym text) AS
$func$
DECLARE
   _nr text;
BEGIN
FOR _nr IN
   SELECT DISTINCT substring(ku,'[0-9]+')
   FROM   public."table_data_C"
LOOP
   RETURN QUERY EXECUTE format(
      'SELECT t.cpa, _nr, p.vym 
       FROM   public."table_data_C" t
       LEFT   JOIN %I p USING (cpa)
       WHERE  t.ku LIKE (_nr || '%')'
     , 'pa' || _nr
     );
END LOOP;

END
$func$ LANGUAGE plpgsql;