如何从SQL Server中的一个DB字段创建多个列?

时间:2009-07-28 19:53:37

标签: sql-server select join subquery table-relationships

我在PropertyValue表格中有一个名为UserProfile的字段,其中包含地址,电话号码,名字,姓氏,用户名,城市等信息...此处的每条记录table由UserId与用户相关联,它还与ProfilePropertyDefinition相关联,其中包含每个属性的定义(即PropertyName)。

通过这种关系,我可以获得所有属性值及其属性名称。我想从这两列(PropertyValue,PropertyName)中提取数据并创建一个类似于此的表:

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

所以,我想知道我是否可以使用SQL语句来执行此操作,这是我的理由:

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'))

但这没有用,有些东西看起来很奇怪......任何人都知道如何选择一列并在几个不同的列中显示它的值?

7 个答案:

答案 0 :(得分: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 :(得分:1)

就个人而言,我现在就停下来考虑一下这个设计对性能有多糟糕。这通常是用于存储此类数据的非常差的技术。如果你想要展示20个职业,你将不得不加入(并且因为你不能保证每个财产都会被代表)而加入这个表20次。此外,如果这是您的数据结构的核心(因为它听起来像是您似乎存储的数据类型),几乎每个查询都需要做一些类似的事情,性能将是非常糟糕的。有时候这是最好的模型(当你无法事先知道需要存储哪些属性时),但大多数时候,它的使用是一个糟糕设计的标志。

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

答案 2 :(得分:0)

我猜你可以多次从同一张桌子中做出选择。 假设tA是具有UserProfileID,PropertyDefinition和PropertyValue

的名称表

你可以做到

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 ....

不理想,但它会起作用

答案 3 :(得分:0)

您需要多次加入表格(与字段一样多次):

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'
...

请注意,这取决于它们是UserProfile中的一些ID字段,您可以使用它来将同一用户的所有行绑定在一起。

答案 4 :(得分:0)

假设模式如

UserProfile#
{userid,
ProfileName, 
propertyValue
}

你想做

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'

答案 5 :(得分:0)

我会写这样的查询:

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

答案 6 :(得分:0)

我需要了解更多关于你的表格sturtures以及你想要了解的内容,但是一个选项可能是创建一个SQL标量函数来重新调整属性的值。我正在对表名和数据库设置做一些假设,但试试这个......

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 up.UserProfileID=@UserProfileID

    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]