2010-11-05 3 views
0

Ma table 'people' a une ligne par personne, et cette personne a une division (non unique) et une société (non unique).SQL se joint à plusieurs enregistrements en un avec une valeur par défaut

J'ai besoin de joindre les gens à p_features, c_features, d_features sur:

people.person=p_features.num_value 
people.division=d_features.num_value 
people.company=c_features.num_value 

... d'une manière que s'il y a un match record en p_features/d_features/c_features seulement, il serait retourné, mais si c'était dans 2 ou 3 des tables, l'enregistrement le plus spécifique serait retourné.

De mes données de test ci-dessous, par exemple, une requête pour personne = 1 retournerait « FAUX »
personne 3 retourne peut-être, personne 4 retourne vrai, et personne 9 retourne par défaut

Le plus gros problème est que il y a 100 fonctionnalités et j'ai des requêtes qui doivent tous les retourner dans une rangée. Ma tentative précédente était une fonction qui interrogeait sur la fonction, num_value dans chaque table et faisait un foreach, mais 100 caractéristiques * 4 tables signifiait 400 lectures et il a arrêté la base de données il était si lent quand j'ai chargé quelques millions de lignes de Les données.

create table p_features (
     num_value int8, 
     feature varchar(20), 
     feature_value varchar(128) 
); 
create table c_features (
     num_value int8, 
     feature varchar(20), 
     feature_value varchar(128) 
); 
create table d_features (
     num_value int8, 
     feature varchar(20), 
     feature_value varchar(128) 
); 
create table default_features (
     feature varchar(20), 
     feature_value varchar(128) 
); 
create table people (
     person int8 not null, 
     division int8 not null, 
     company int8 not null 
); 
insert into people values (4,5,6); 
insert into people values (3,5,6); 
insert into people values (1,2,6); 
insert into p_features values (4,'WEARING PANTS','TRUE'); 
insert into c_features values (6,'WEARING PANTS','FALSE'); 
insert into d_features values (5,'WEARING PANTS','MAYBE'); 
insert into default_features values('WEARING PANTS','DEFAULT'); 

Répondre

0

Vous devez transposer les entités en lignes avec un classement. Ici, j'ai utilisé une expression de table commune. Si votre produit de base de données ne les prend pas en charge, vous pouvez utiliser des tables temporaires pour obtenir le même effet.

;With RankedFeatures As 
    (
    Select 1 As FeatureRank, P.person, PF.feature, PF.feature_value 
    From people As P 
     Join p_features As PF 
      On PF.num_value = P.person 
    Union All 
    Select 2, P.person, PF.feature, PF.feature_value 
    From people As P 
     Join d_features As PF 
      On PF.num_value = P.division 
    Union All 
    Select 3, P.person, PF.feature, PF.feature_value 
    From people As P 
     Join c_features As PF 
      On PF.num_value = P.company 
    Union All 
    Select 4, P.person, DF.feature, DF.feature_value 
    From people As P 
     Cross Join default_features As DF 
    ) 
    , HighestRankedFeature As 
    (
    Select Min(FeatureRank) As FeatureRank, person 
    From RankedFeatures 
    Group By person 
    ) 
Select RF.person, RF.FeatureRank, RF.feature, RF.feature_value 
From people As P 
    Join HighestRankedFeature As HRF 
     On HRF.person = P.person 
    Join RankedFeatures As RF 
     On RF.FeatureRank = HRF.FeatureRank 
      And RF.person = P.person 
Order By P.person 
+0

C'est génial. Je n'ai pas de tables communes dans Informix alors j'ai fait une vue et une fonction de classement. Merci beaucoup pour ton effort! – user490231

+0

Encore une chose, puisque si j'ai 5 caractéristiques, j'ai 5 lignes, puis-je faire une vue de ceci dans une vue horizontale comme: sélectionner une personne, (valeur lorsque feature = 'PANTALON DE PORT »), (valeur lorsque feature = 'PORT DE CHAPEAU'), etc de votre tableau ci-dessus .. espérons que cela a du sens. – user490231

0

Je ne sais pas si je l'avais très bien compris votre question, mais d'utiliser JOIN, vous avez besoin de votre table déjà chargée et puis utilisez la SELECT déclaration avec INNER JOIN, LEFT JOIN ou tout vous devez montrer. Si vous postez un peu plus d'informations, rendez-le facile à comprendre.

0

Il y a certains aspects de votre schéma que je ne comprends pas, comme comment se rapporter à la table default_features s'il n'y a aucune correspondance dans aucune des tables spécifiques. La seule condition de jointure possible est feature, mais s'il n'y a pas de correspondance dans les 3 autres tables, il n'y a pas de valeur à rejoindre. Donc, dans mon exemple, j'ai codé en dur le DEFAUT car je ne peux pas penser à autre chose pour l'obtenir.

Espérons que cela peut vous aider à démarrer et si vous pouvez clarifier le modèle un peu plus, la solution peut être affinée.

select p.person, coalesce(pf.feature_value, df.feature_value, cf.feature_value, 'DEFAULT') 
    from people p 
     left join p_features pf 
      on p.person = pf.num_value 
     left join d_features df 
      on p.division = df.num_value 
     left join c_features cf 
      on p.company = cf.num_value 
Questions connexes