我有一个属性值表av
,如下所示:
| attribute | value |
~~~~~~~~~~~~~~~~~~~~~
| a1 | A1 |
| b1 | BB1 |
| b2 | BB2 |
为简单起见,假设varchar(255)
和attribute
列上的value
,attribute
上的唯一索引。
我需要在查询中使用特定属性的值,如下所示:
SELECT *
FROM t1
,t2
WHERE t1.a1 = "A1" -- Value of "a1" attribute
AND t1.id = t2.id
AND t2.b1 = "BB1" -- Value of "b1" attribute
AND t2.b2 = "BB2" -- Value of "b2" attribute
是否有一种优雅的方法在Sybase ASE(12或15)中执行此操作,可以很好地扩展,因为我们增加了表和属性的数量?
按“比例”,我的意思是4-5个连接表需要~10-20个属性
我可以想到以下解决方案,所有这些似乎都很糟糕:
解决方案1:明显:加入AV表,每个属性一次
SELECT *
FROM t1
,t2
,av AS 'av_a1'
,av AS 'av_b1'
,av AS 'av_b2'
WHERE t1.a1 = av_a1.value
AND t1.id = t2.id
AND t2.b1 = av_b1.value
AND t2.b2 = av_b2.value
AND av_a1.attribute = "a1"
AND av_b1.attribute = "b1"
AND av_b2.attribute = "b2"
优点:明显。
缺点:就代码质量和性能而言,它的评分非常差。
解决方案2:避免使用变量进行多次连接的麻烦
declare @a1 varchar(255)
select @a1 = value FROM av WHERE attribute = "a1"
declare @b1 varchar(255)
select @b1 = value FROM av WHERE attribute = "b1"
declare @b2 varchar(255)
select @b2 = value FROM av WHERE attribute = "b2"
SELECT *
FROM t1
,t2
WHERE t1.a1 = @a1
AND t1.id = t2.id
AND t2.b1 = @b1
AND t2.b2 = @b2
优点:没有更多的额外加入,使查询既丑陋又效果不佳。
缺点:就代码质量而言,缩放程度稍差(需要使用新属性添加新变量)。
有更好的解决方案吗?
答案 0 :(得分:1)
我不确定where
语句中的附加条款是什么(将一个表中的值与另一个表中的属性进行比较)。以下内容在连接之前展平属性:
SELECT *
FROM t1 join
t2
on t1.id = t2.id join
(select av.id,
MAX(case when av.attribute = 'a1' then av.value end) as a1,
MAX(case when av.attribute = 'b1' then av.value end) as b1,
MAX(case when av.attribute = 'b2' then av.value end) as b2
from av
group by av.id
) attr
on attr.id = t1.id
这是有效的,假设属性中没有重复项 - 通常在使用属性表时不存在重复项。您可以在where
条件中添加回来,如果您愿意,我只是不明白为什么他们在那里。
此外,您应该切换到ANSI标准连接语法。
如果你没有身份证,你可以做同样的事情:
SELECT *
FROM t1 join
t2
on t1.id = t2.id cross join
(select MAX(case when av.attribute = 'a1' then av.value end) as a1,
MAX(case when av.attribute = 'b1' then av.value end) as b1,
MAX(case when av.attribute = 'b2' then av.value end) as b2
from av
) attr
on attr.id = t1.id
where <whatever you want>
答案 1 :(得分:0)
使用Entity-Attribute-Value设计从根本上讲是非关系的,因此在SQL中查询它就像在行中描述一个逻辑实体的属性一样笨拙且效率低下。
为了减轻在SQL中执行此操作的成本,我经常建议在存储在数据库中时获取所有行,然后将属性应用于应用程序代码中的实体实例,一次一行。
这是另一个问题,示例PHP代码展示了我的意思:
Create a summary result with one query
重新评论并发表评论:
你在这里拍摄信使。
你问:
在Sybase ASE(12或15)中是否有一种优雅的方法可以在我们增加表和属性的数量时进行扩展?
每个查询多行EAV数据到一行结果集的方法,无论是通过连接还是通过旋转,都需要您知道属性集,并且这些属性在您准备查询时是固定的。由于SQL基于关系模型,因此在查询执行时,结果集的列不能动态扩展。
因此,如果您有一个数据模型,其中表和属性的数量会不时扩展,那么每次添加属性时,您都会发现自己正在更改数据透视查询代码。
您可以根据不同属性的数量动态生成数据透视查询,但这也需要应用程序代码,因为您需要查询当前属性然后构建查询。
另一种方法是获取所有数据,每行结果集一个属性,并编写代码以将它们“重新组合”为应用程序端的逻辑实体。
动态数据透视查询始终需要应用程序代码 - 在查询之前或之后。
对不起,你不喜欢那个答案。