2009-12-18 139 views
1

我希望你能帮我解决我们这个任务。动态sql数据透视表

本来我们有这些表:

hwtype 
id name 
1 router 
2 switch 

hwelement 
id idhwtype name 
1 1   RTR1 
2 1   RTR2 
3 2   SWT1 

hwattributes 
id idhwtype name 
1 1  speed 
2 1  IP 
3 2  ports 

hwtypeattributes 
id idhwelement idhwattribute value 
1 1    1    100mb 
2 1    2    172.16.3.23 
3 2    1    10mb 
4 2    2    172.16.3.26 
5 3    3    8 

我们现在需要的是呈现这样的数据的功能(根据hwtype)

为hwtype.name =路由器

element speed IP 
RTR1  100mb 172.16.3.23 
RTR2  10mb 172.16.3.26 

这个想法是使表能够包含新的元素类型,元素和属性,而不必修改表编码。

我一直在寻找例子,但不幸的是我发现了很好的值,这些值是我没有考虑过的值。

在此先感谢您的帮助

+4

当询问有关SQL的问题,一定要与你使用的品牌RDBMS的标记。例如。 'sql-server','oracle','mysql'等等。它对于答案很重要。 –

+1

您不是第一个梦想使用Entity-Value体系结构不需要更改数据库的系统的人。不幸的是,你最终可能不会是最后诅咒这个决定的最后一个:(如果改变架构还不算太晚,你应该考虑它。 –

回答

0

您正在使用EAV反模式。这打破了关系数据库设计的各种规则,正如您发现的那样,获取数据非常尴尬。这种设计还有其他许多弱点,在其他地方进行了介绍。

阅读文章“Bad CaRMa”为的EAV系统如何摧毁一个公司一个伟大的故事。

这里是你必须做的就是路由器属性,你的数据库的内容:

SELECT e.name AS "element", 
     speedval.value AS "speed", 
     ipval.value AS "IP", 
     portsval.value AS "Ports" 
FROM hwtype t 
JOIN hwelement e ON (e.idhwtype = t.id) 
JOIN hwattributes speed ON (speed.idhwtype = t.id AND speed.name = 'speed') 
LEFT OUTER JOIN hwtypeattributes speedval 
    ON (speedval.idhwattribute = speed.id AND speedval.idhwelement = e.id) 
JOIN hwattributes ip ON (ip.idhwtype = t.id AND ip.name = 'ip') 
LEFT OUTER JOIN hwtypeattributes ipval 
    ON (ipval.idhwattribute = ip.id AND ipval.idhwelement = e.id) 
JOIN hwattributes ports ON (ports.idhwtype = t.id AND ports.name = 'ports') 
LEFT OUTER JOIN hwtypeattributes portsval 
    ON (portsval.idhwattribute = ports.id AND portsval.idhwelement = e.id) 
WHERE t.name = 'router'; 

请注意,你需要一对额外加入每个属性的,如果你坚持要获取的所有属性给定元素在一行上。这对于SQL优化器来说很快就变得非常昂贵。

它更容易获取的多行的属性,并在应用程序代码理清:

SELECT e.name AS "element", a.name, v.value 
FROM hwtype t 
JOIN hwelement e ON (e.idhwtype = t.id) 
JOIN hwattributes a ON (a.idhwtype = t.id) 
JOIN hwtypeattributes v ON (v.idhwattribute = a.id AND v.idhwelement = e.id) 
WHERE t.name = 'router';