在我看来,您尝试实现一种 EAV(实体-属性-值)设计。
你的表看起来不错,但这种设计本身就需要复杂的 SQL。
有不同的方法可以做到这一点,但根据你上面的故事,我会采用这样的方法。
Subject --< Process --< RelationshipProcessProperty >-- Property
您的属性将如下所示:
"Property"
PK PropertyId
Name
您的 RelationshipProcessProperty 可能如下所示:
"RelationshiipProcessProperty"
PK RelationshipProcessProperty
FK Process
FK Property
Value
您的 SQL 会变得复杂。进行这样的“通用”设计意味着您要在同一个表中查找多个值。
; with Property1 as(
SELECT
proc.Id as ProcessId,
prop.Name,
rrp.Value
FROM Subject s
LEFT JOIN Process proc
ON s.SubjectId = proc.SubjectId
LEFT JOIN RelationshipProcessProperty rpp
on proc.ProcessId = rpp.ProcessId
LEFT JOIN Property prop
on rpp.PropertyId = prop.PropertyId
WHERE
s.Name = "Subject1"
AND
proc.Name = "Process1"
AND
prop.Name = "Property1"
)
, Property2 as(
SELECT
proc.Id as ProcessId,
prop.Name,
rrp.Value
FROM Subject s
LEFT JOIN Process proc
ON s.SubjectId = proc.SubjectId
LEFT JOIN RelationshipProcessProperty rpp
on proc.ProcessId = rpp.ProcessId
LEFT JOIN Property prop
on rpp.PropertyId = prop.PropertyId
WHERE
s.Name = "Subject1"
AND
proc.Name = "Process1"
AND
prop.Name = "Property2"
)
SELECT
p1.Name,
p1.Value,
p2.Name,
p2.Value
FROM
Property1 p1
LEFT JOIN Property2 p2
on p1.ProcessId = p2.ProcessId
您可以使用此方法获取同一进程的多个属性。
为了具有指定进程的指定属性,您需要创建进程类型表:
"ProcessType"
PK ProcessType
Type
这确实意味着您需要向您的进程表添加一个外键以将其链接到它的类型。然后,您可以使用定义所有可用类型的关系表将 ProcessType 表链接到 Property 表。
"EligibleProcessProperties"
PK EligibleprocessPropertiesId
FK ProcessType
Fk Property
然后要找出该进程类型的所有可用属性,您将有一个相对简单的查询
SELECT
p.Name
FROM
ProcessType pt
LEFT JOIN EligibleProcessProperties epp
on pt.ProcessTypeId = epp.ProcessTypeId
LEFT JOIN Property p
on epp.PropertyId = p.PropertyId
WHERE
pt.Type = "Type1"
我认为这是您正在寻找的那种东西(尽管我可能完全不在意)。如果这是您正在寻找的内容,那么这里有一篇非常好的帖子,它提出了一些要点。
另外,我几乎 100% 有更好的方法来做我的长 ';with' 查询——但这就是我所知道的。希望其他人可以提供更好的。关键是,通过这种设计,您将需要以一种或另一种方式进行子查询。