2009-07-28 18 views
0

J'ai un champ appelé PropertyValue dans le tableau UserProfile qui peut contenir des informations pour l'adresse, le numéro de téléphone, le prénom, le nom, le nom d'utilisateur, la ville, etc ... chaque enregistrement de ce tableau est associé à un utilisateur par UserId, il est également associé à un ProfilePropertyDefinition qui contient la définition de chacune des propriétés (par exemple, PropertyName).Comment puis-je créer plusieurs colonnes à partir d'un champ de base de données dans SQL Server?

Grâce à cette relation, je peux obtenir toutes les valeurs de propriété avec leurs noms de propriété. Ce que je voudrais le faire pour extraire les données de ces deux colonnes (PropertyValue, PropertyName) et créer une table semblable à ceci:

First Name | Last Name | Email | Phone | City | Country 
------------------------------------------------------- 
      |   |  |  |  | 

Donc, je voulais savoir si je peux utiliser une instruction SQL pour faire cela, voici mon aller à elle:

SELECT FirstName = (SELECT PropertyValue FROM UserProfile WHERE PropertyDefinitionID = (SELECT PropertyDefinitionID WHERE PropertyName = 'first name')), 
LastName = (SELECT PropertyValue FROM UserProfile WHERE PropertyDefinitionID = (SELECT PropertyDefinitionID WHERE PropertyName = 'last name')), 
Email = (SELECT PropertyValue FROM UserProfile WHERE PropertyDefinitionID = (SELECT PropertyDefinitionID WHERE PropertyName = 'email')) 

Mais cela ne fonctionne pas et quelque chose semble vraiment bizarre à ce sujet ... Quelqu'un sait comment prendre une colonne et afficher ses valeurs dans plusieurs colonnes différentes?

Répondre

1
SELECT fn.PropertyValue FirstName, 
     ln.PropertyValue LastName, 
     etc... 

From UserProfile fN 
    Join UserProfile lN 
     On fN.PropertyName = 'first name' 
     And ln.PropertyName = 'last name' 
     And fn.user = ln.user 
    Join UserProfile eM 
     On fN.PropertyName = 'first name' 
     And eM.PropertyName = 'email' 
     And eM.user = fn.user 

(

+1

Pourquoi Quelqu'un at-il remanié cela? Qu'est-ce qui rend cette réponse meilleure que les autres? Je voudrais savoir si je peux choisir la meilleure réponse ... – Matt

+0

Je ne sais pas, je voudrais essayer ceci et comparer la performance à ma solution. Je pense que vous constaterez que le mien fonctionne beaucoup mieux si la table est grande et que vous avez beaucoup de champs à construire (parce que cette solution utilise une jointure pour chaque champ). – automatic

0

Je suppose que vous pourriez faire un choix de la même table plusieurs fois. Disons que tA est la table de nom avec UserProfileID, PropertyDefinition et PropertyValue

Vous pouvez faire

select 
t1.PropertyValue as FirstName, 
t2.PropertyValue as LastName, 
... 
FROM 
tA as t1, tA as t2, .... 
WHERE 
t1.PropertyDefinition Like 'FirstName' AND 
t2.PropertyDefinition Like 'LastName' AND 
.... 
AND 
t1.UserId = @user AND 
t2.UserID = @user .... 

Pas idéal, mais il travaillerait

+0

Vous pouvez structurer également la requête en tant que groupe de jointures internes, mais je * pense * le derrière l'opération de scènes serait proche de la même (ne me citez pas là-dessus identique) – Matt

0

Vous devez joindre les tables plusieurs fois (comme autant de fois que vous avez des champs):

SELECT UPFN.PropertyValue AS FirstName, UPLN.PropertyValue AS LastName, ... 
FROM UserProfile UPFN 
INNER JOIN ProfilePropertyDefinition PPDFN ON PPDFN.PropertyDefinitionID = UPFN.PropertyDefinitionID AND PPDFN.PropertyName = 'first name' 
INNER JOIN UserProfile UPLN ON UPLN.id = UPFN.id 
INNER JOIN ProfilePropertyDefinition PPDLN ON PPDLN.PropertyDefinitionID = UPLN.PropertyDefinitionID AND PPDLN.PropertyName = 'last name' 
... 

Notez que ce repose sur leur être un champ d'identité dans le UserProfile que vous pouvez utiliser à t c'est-à-dire toutes les lignes pour le même utilisateur ensemble.

0

schéma En supposant que

UserProfile# 
{userid, 
ProfileName, 
propertyValue 
} 

Vous voudrait faire

SELECT 
FirstName.PropertyValue FirstNAme, 
LastName.PropertyValue LastName, 
FROM 
users 
JOIN (USERPROFILE) FirstName ON 
FirstName.userid = users.userid 
and PropertName ='FirstName' 
JOIN (USERPROFILE) LastName ON 
LastName.userid = users.userid 
and PropertName ='LastName' 
0

Je voudrais écrire la requête comme ceci:

Select 
    aa.userId, 
    Coalesce(Max(Case when PropertyName = 'First Name' then PropertyValue else '' end),'') as FirstName, 
    and so on 
from 
    UserTable as aa 
left join 
    UserProfile as bb 
    on 
    aa.UserId = bb.UserId 
left join 
    ProfilePropertyDefinition as cc 
    on bb.PropertyDefinitionId = cc.PropertdefinitionId 
group by 
    aa.UserId 
0

J'aurais besoin d'en savoir plus sur vos tables et ce que vous essayez de réaliser, mais une option pourrait être de créer une fonction scalaire SQL pour récupérer les valeurs des propriétés. Je fais quelques hypothèses sur les noms de table et la configuration de base de données, mais essayez ceci sur ...

CREATE FUNCTION [dbo].[UserProperty] 
(
    @UserProfileID UNIQUEIDENTIFIER, @Property VARCHAR(200) 
) 
RETURNS VARCHAR(max) 
AS 
BEGIN 
    -- Declare the return variable here 
    DECLARE @Value AS VARCHAR(MAX) 
    SELECT @Value = PropertyValue FROM UserProfile up INNER JOIN PropertyDefinitions pd ON 
    up.PropertyDefinitionID = pd.PropertyDefinitionID 
    WHERE pd.PropertyName = @Property AND [email protected] 

    RETURN ISNULL(@Value,'') 

END 

SELECT 
    [dbo].[UserProperty](UserProfileID, 'first name') AS [First Name], 
    [dbo].[UserProperty](UserProfileID, 'last name') AS [Last Name], 
    [dbo].[UserProperty](UserProfileID, 'email') AS [Email] 
FROM 
    [Users] 
1

Personnellement, je cesserais en ce moment et d'examiner à quel point cette conception sera pour la performance. C'est en général une très mauvaise technique à utiliser pour stocker ce type de données. Si vous avez 20 proerties que vous voulez afficher, vous devrez vous joindre (et joindre à cela car vous ne pouvez pas garantir que chaque propriété sera représentée) à cette table 20 fois. En outre, si cela est au cœur de votre structure de données (comme il semble que ce soit à partir du type de données que vous semblez stocker), pratiquement chaque requête devra faire quelque chose de similaire et la performance sera atroce.Il y a un temps où c'est le meilleur modèle (quand vous n'avez aucun moyen de savoir à l'avance quelles propriétés devront être stockées), mais la plupart du temps, son utilisation est un signe d'un mauvais design.

http://en.wikipedia.org/wiki/Entity-Attribute-Value_model

+0

Je suis d'accord, mais c'est la façon dont les profils utilisateur sont configurés par défaut (DNN sur Asp.Net). Sauf si je passe par et créer des tables pour chacun qui doit être modifié, recâbler tous les modules DNN qui utilisent ces tables, et créer des modules d'enregistrement et de profil complètement nouveaux qui peuvent gérer une table de cette façon et gérer l'ajout de nouvelles colonnes à une table pour chaque nouvelle propriété de profil personnalisée ... La technique ne va pas changer ... Je pense que je vais prendre le coup de la performance. – Matt