2010-06-02 67 views
3

说帮助我有2个表:需要使用SQL查询

Person 

- Id 
- Name 

PersonAttribute 

- Id 
- PersonId 
- Name 
- Value 

而且,让我们说,每个人有2种属性(比如,性别和年龄)。样本的记录是这样的:

Person->Id = 1 
Person->Name = 'John Doe' 

PersonAttribute->Id = 1 
PersonAttribute->PersonId = 1 
PersonAttribute->Name = 'Gender' 
PersonAttribute->Value = 'Male' 

PersonAttribute->Id = 2 
PersonAttribute->PersonId = 1 
PersonAttribute->Name = 'Age' 
PersonAttribute->Value = '30' 

问题:我该如何查询该这样,我得到这样一个结果:

“李四”,“男”,“30”

回答

4
SELECT p.name, p1.Value, p2.Value 
    FROM Person p, PersonAttribute p1, PersonAttribute p2 
    WHERE p.Id = p1.PersonId AND p.Id = p2.PersonId 
     AND p1.Name = 'Gender' AND p2.Name = 'Age' 
+1

这不能缩放以提取N个通用属性及其值。 – Timothy 2010-06-02 06:39:35

1

抛开设计,你总是可以得到PIVOT的结果,但你需要知道你预先选择了多少属性。

3

我认为你需要重新设计你的架构。 为什么不呢?

Person 

- Id 
- Name 
- Gender 
- Birthday 
... 
+2

+1完全同意。看起来年龄存储在PersonAttribute-> Value字符串列中,以及诸如“Male”之类的内容(并且您指出这应该是派生出来的) – 2010-06-02 06:33:46

+0

我不同意。 OP设计了一个通用属性模式,可能使用户可以定义他们自己的属性并分配他们自己的值。不过,他的例子是一个很差的例子。 – Timothy 2010-06-02 06:38:53

+0

@ msi77&@martinsmith:模式要求实体A具有0个或更多属性。 “人”的例子就是这样一个例子。我用它来简化我的问题并获得更快的响应。 – StackOverflowNewbie 2010-06-02 06:49:40

0
SELECT Name, g.Value, a.Value 
FROM Person, 
PersonAttribute g INNER JOIN ON g.Name = "Gender", 
PersonAttribute a INNER JOIN ON a.Name = "Age" 
2

SELECT p.Name,g.Value,a.value中
FROM人员P INNER JOIN PersonAttribute克ON p.Id = g.Id AND g.Name = “性别”
INNER JOIN PersonAttribute a ON p.Id = a.Id AND a.Name =“Age”

1

看看有没有简单的方法来做到这一点。

透视表(已被另一个答复中提到)的概念基本上是你在找什么,但透视表需要你知道你要使用的列的名称。很显然,当你想利用这种桌子设计的力量时,这是一个问题!

在我以前的生活,我只是看中了列的X号,如20-30,如果他们不存在,则该行集包含了一堆空值。没什么大不了。

select piv.name, 
    max(case piv.a_name when 'Gender' then piv.a_value else null end) as Gender, 
    max(case piv.a_name when 'Age' then piv.a_value else null end) as Age, 
    max(case piv.a_name when 'Hobby' then piv.a_value else null end) as Hobby 
from 
(select p.name as name, pa.name as a_name, pa.value as a_value 
from person p, personattribute pa 
where p.id = pa.personid) piv 
group by piv.name 

这将产生像这样的输出:

name | gender | age | hobby 
-----------+--------+-----+--------- 
Bob Swift | Male |  | Reading 
John Doe | Male | 30 | 
(2 rows) 

这是非常该死接近你在找什么。我会将剩下的部分留给应用层。

我也强烈建议您包含属性名称作为返回值的一部分,提供上下文的值。

这类所谓的实体属性的设计往往最终不得不依靠特定的服务器功能,存储过程和硬编码查询的组合。