2017-06-07 2 views
0

j'ai un type composite qui ressembleCarte pour nom de table et rejoindre

CREATE TYPE member AS (
    id BIGINT, 
    type CHAR(1) 
); 

J'ai une table qui repose sur ce type member avec un tableau.

CREATE TABLE relation (
    id BIGINT PRIMARY KEY, 
    members member[] 
); 

J'ai trois autres tables chacune avec un schéma différent (mais avec champ id commun)

CREATE TABLE table_x (
    id BIGINT PRIMARY KEY, 
    some_text TEXT 
); 

CREATE TABLE table_y (
    id BIGINT PRIMARY KEY, 
    some_int INT 
); 

CREATE TABLE table_z (
    id BIGINT PRIMARY KEY, 
    some_date TIMESTAMP 
); 

terrain type dans le type member est juste un personnage à découvrir table membre spécifique appartient. Une ligne dans le tableau relation peut avoir un mélange de différents type s.

J'ai un scénario qui exige le retour relation ids avec au moins un member remplissant une certaine condition basée sur son type (disons pour x =>some_text est pas vide ou y =>some_int est supérieur à 10 ou z =>some_date est une semaine est à partir de maintenant).

Je peux mettre en œuvre ce scénario du côté de l'application en faisant plusieurs requêtes à la base de données:

  • unnest relation Table
  • recueillir member données par relation
  • faire de nouvelles demandes pour savoir relation s

Je me demande s'il existe un moyen de mapper des valeurs de colonne aux noms de table et rejoignez-les.

+0

Avez-vous des données d'échantillon et résultat attendu? – cachique

+0

Cela ressemble à une conception de base de données pas si bonne que nous entrons dans le territoire des noms de tables dynamiques.Il n'y a aucun moyen dans une seule requête de dire "Utiliser la valeur d'un champ dans cette table pour obtenir le nom de la table à laquelle je dois me joindre, joindre-y, et sélectionner les données". Bien que si vous pouvez expliquer les exemples dont vous avez besoin, il existe peut-être une solution de contournement pour joindre toutes les tables et fusionner. – JNevill

Répondre

0

@JNevill avait un bon point sur cette conception de base de données. Bien que cette approche ne semble pas optimale, elle maintient les définitions des tables clairement séparées sans aucune relation entre elles. En outre, la taille de la table relation est relativement faible par rapport aux trois autres tables.

je résolu le problème en allant chercher simplement des lignes par type et de les fusionner:

SELECT relation.* FROM relation, UNNEST(relation.members) member INNER JOIN table_x ON member.id = table_x.id WHERE member.type = 'x' AND table_x.some_text = 'some text value' 
UNION 
SELECT relation.* FROM relation, UNNEST(relation.members) member INNER JOIN table_y ON member.id = table_y.id WHERE member.type = 'y' AND table_y.some_int = 123 
UNION 
SELECT relation.* FROM relation, UNNEST(relation.members) member INNER JOIN table_z ON member.id = table_z.id WHERE member.type = 'z' AND table_z.some_date > '2017-01-11 00:00:00'; 
0

Assomption

  • Im en supposant que matrice relation.members ne possède pas plus d'un élément de membre du même type. Correct?

requête pour essayer

with unnested_members as (
-- Unnest members array 
select id, unnest(members) members 
from relation 
) 
, members_joined as (
-- left join on a per type basis with table_x, table_y and table_z. 
select r.id, (r.members).id idext, (r.members).type, 
     x.some_text, y.some_int, z.some_date -- more types, more columns here 
from unnested_members r 
    left join table_x x on (x.id = (r.members).id and (r.members).type = 'x') 
    left join table_y y on (y.id = (r.members).id and (r.members).type = 'y') 
    left join table_z z on (z.id = (r.members).id and (r.members).type = 'z') 
    -- More types, more tables to left join 
) 
select id, 
    max(some_text) some_text, -- use max() to get not null value for this id 
    max(some_int) some_int, -- use max() to get not null value for this id 
    max(some_date) some_date -- use max() to get not null value for this id 
    -- more types, more max() columns here 
from members_joined 
group by id -- get one row per relation.id with data from joined table_* columns 

Si vous devez inclure plusieurs tables, vous devez inclure ces tables dans la partie left join, inclure la colonne dans la liste select et dans la section max() ainsi.

+0

'relation.members' est un tableau. Il peut avoir plusieurs membres du même type. – mert