PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Junção à esquerda com o nome da tabela dinâmica derivado da coluna


De qualquer forma, você precisa de SQL dinâmico.

Nome da tabela como parâmetro fornecido

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;

Ligar:
SELECT * FROM foo(456887)

Geralmente, você limparia os nomes das tabelas com format ( %I ) para evitar injeção de SQL. Com apenas um integer como entrada dinâmica que não é necessária. Mais detalhes e links nesta resposta relacionada:
INSERIR com o nome da tabela dinâmica na função de gatilho

Modelo de dados


Pode haver boas razões para o modelo de dados. Como particionamento / fragmentação ou privilégios separados ...
Se você não tiver um motivo tão bom, considere consolidar várias tabelas com esquema idêntico em uma e adicione o number como coluna. Então você não precisa de SQL dinâmico.

Considere a herança . Então você pode adicionar uma condição em tableoid para recuperar apenas linhas de uma determinada tabela filha:
SELECT * FROM parent_table
WHERE  tableoid = 'pa456887'::regclass

No entanto, esteja ciente das limitações de herança. Respostas relacionadas:

Nome da 2ª tabela dependendo do valor na 1ª tabela


Derivar o nome da tabela de junção dos valores na primeira tabela complica dinamicamente as coisas.

Para apenas algumas mesas


LEFT JOIN cada um em tableoid . Há apenas uma correspondência por linha, então 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 muitas mesas


Combine um loop com 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;