PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Join sinistro con nome tabella dinamico derivato dalla colonna

In ogni caso, hai bisogno di SQL dinamico.

Nome tabella come parametro specificato

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;

Chiama:

SELECT * FROM foo(456887)

In genere, sanificheresti i nomi dei tavoli con format ( %I ) per evitare l'iniezione SQL. Con solo un integer come input dinamico che non è necessario. Maggiori dettagli e collegamenti in questa risposta correlata:
INSERT con nome tabella dinamica nella funzione trigger

Modello di dati

Potrebbero esserci buone ragioni per il modello di dati. Come il partizionamento/sharding o privilegi separati...
Se non hai una buona ragione, considera di consolidare più tabelle con schema identico in una e aggiungi il number come colonna. Allora non hai bisogno di SQL dinamico.

Considera ereditarietà . Quindi puoi aggiungere una condizione su tableoid per recuperare solo righe da una determinata tabella figlio:

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

Siate tuttavia consapevoli delle limitazioni per l'ereditarietà. Risposte correlate:

Nome della 2a tabella in base al valore nella 1a tabella

Derivare il nome della tabella di join dai valori nella prima tabella complica le cose in modo dinamico.

Solo per pochi tavoli

LEFT JOIN ciascuno su tableoid . C'è solo una corrispondenza per riga, quindi usa 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

Per molti tavoli

Combina un ciclo con query dinamiche:

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;