1

我有点 SQL 新手,所以我绝对可以使用一些帮助来散列特定查询的一般设计。我将在下面给出一个我正在尝试做的 SQL 示例。它可能包含一些语法错误,对此我深表歉意——我只是想在运行和测试之前先把设计搞定!

旁注-我对设计方案的控制为 0,因此重新设计不是一种选择。由于我的疏忽,我的示例表可能存在错误,但自下而上值搜索的整体设计方案将保持不变。我正在查询一个现有的数据库,其中已经有大量数据。

场景是这样的:有一棵元素树。每个元素都有一个 ID 和一个父 ID(下面的表格布局)。父 ID 是其自身的递归外键。还有一个包含值的表。每个值都有一个 elementID,它是元素表的外键。因此,要获取特定元素的特定变量的值,您必须连接两个表。

变量层次结构通过继承自下而上。如果你有一个元素并且想要获取它的变量值,你首先查看那个元素。如果它没有值,则检查元素的父元素。如果那不检查父母的父母 - 一直到顶部。当您到达顶部时,保证每个变量都有一个值!(如果我搜索 variableID 21- 我知道 21 将存在。如果不在底部,那么肯定在顶部)树上的最低元素获得优先权,但是 - 如果底部元素具有该变量的值,请不要不要再往上走!

这些表大致如下所示:

Element_Table
--------------
elementID (PK)
ParentID (FK to elementID)

Value_Table 
--------------
valueID (PK)
variableID
value (the value that we're looking for)
elementID (FK to Element_Table.elementID)

所以,我想做的是创建一个函数,它可以干净地(这里的关键词。漂亮、干净和高效的代码)自下而上地在整个树中搜索变量值。一旦我找到它-返回该值并继续前进!

这是我在想的一个例子:

CREATE FUNCTION FindValueInTreeBottomUp
(@variableID int, @element varchar(50))
RETURNS varchar(50) 
AS
BEGIN
DECLARE @result varchar(50)
DECLARE @ID int
DECLARE @parentID int

SET @result = NULL, @ID = @element
WHILE (@result IS NULL)
    BEGIN
       SELECT @result = vals.value, @parentID = eles.ParentID
       FROM Value_Table vals 
       JOIN Element_Table eles 
       ON vals.elementID = eles.elementID
  WHERE eles.elementID = @ID AND vals.variableID = @variableID
  IF(@result IS NULL)
      @ID = @parentID
      CONTINUE
  ELSE
      BREAK
END

RETURN @result
END

再次,如果有任何语法错误,我深表歉意。仍然是 SQL 新手,还没有运行它!我尤其是函数新手——我可以整天查询,但函数/存储过程对我来说还是相当新的。

那么,那里的 SQL 专家——你能想出一个更好的方法来做到这一点吗?桌子的设计不会改变;我无法控制。我所能做的就是产生查询来检查已经存在的设计。

4

1 回答 1

1

我认为你可以做这样的事情(它未经测试,必须在 sql fiddle 中尝试):

;with cte1 as (
    select e.elementID, e.parentID, v.value
    from Element_Table as e
        left outer join Value_Table as v on e.elementID = e.elementID and v.variableID = @variableID
), cte2 as (
    select v.value, v.parentID, 1 as aDepth
    from cte1 as v
    where v.elementID = @elementID
    union all
    select v.value, v.parentID, c.aDepth + 1
    from cte2 as c
    inner join cte1 as v on v.elementID = c.ParentID
    where c.value is null
)
select top 1 value
from cte2
where value is not null
order by aDepth

测试基础设施:

declare @Elements table (ElementID int, ParentID int)
declare @Values table (VariableID int, ElementID int, Value nvarchar(128))
declare @variableID int, @elementID int

select @variableID = 1, @elementID = 2

insert into @Elements
select 1, null union all
select 2, 1

insert into @Values
select 1, 1, 'test'

;with cte1 as (
    select e.elementID, e.parentID, v.value
    from @Elements as e
        left outer join @Values as v on e.elementID = e.elementID and v.variableID = @variableID
), cte2 as (
    select v.value, v.parentID, 1 as aDepth
    from cte1 as v
    where v.elementID = @elementID
    union all
    select v.value, v.parentID, c.aDepth + 1
    from cte2 as c
        inner join cte1 as v on v.elementID = c.ParentID
    where c.value is null
)
select top 1 value
from cte2
where value is not null
order by aDepth
于 2013-09-13T14:51:21.700 回答