树遍历以查找最';逻辑';两个表之间的SQL联接

树遍历以查找最';逻辑';两个表之间的SQL联接,sql,join,tree,search-tree,Sql,Join,Tree,Search Tree,我正在创建一个类似于报表生成器的应用程序,目的是打造一个对新手非常友好的前端 应用程序的后端将由开发人员管理,开发人员可以构建一个“报告模型”,该模型将指定最终用户要使用的表、字段和联接 我还希望添加不需要报表模型的功能。我的应用程序将扫描目标SQL数据库,并创建一个虚拟模型,其中映射了所有连接和字段 在此之后,我需要能够在表之间生成最“逻辑”或最有效的路径,例如使用最少的联接。类似于旅行推销员的场景 我已经决定使用树映射一个特定表中的所有连接,该表将作为起始节点,以及它可能连接到的所有其他表。

我正在创建一个类似于报表生成器的应用程序,目的是打造一个对新手非常友好的前端

应用程序的后端将由开发人员管理,开发人员可以构建一个“报告模型”,该模型将指定最终用户要使用的表、字段和联接

我还希望添加不需要报表模型的功能。我的应用程序将扫描目标SQL数据库,并创建一个虚拟模型,其中映射了所有连接和字段

在此之后,我需要能够在表之间生成最“逻辑”或最有效的路径,例如使用最少的联接。类似于旅行推销员的场景

我已经决定使用树映射一个特定表中的所有连接,该表将作为起始节点,以及它可能连接到的所有其他表。通过这种方式,我可以进行广度优先树遍历,从理论上找到最“逻辑”的连接路径

我的问题是,并不是所有的数据库都将以一种特别机器逻辑友好的方式进行设置。这意味着,由于特定的表或字段名,人类可能会看到逻辑连接,而我的算法可能不会。(下面是我的算法在c#中的一个简单迭代,它还没有记录表之间的路径)

公共节点findClosestObjToNode(节点节点,T obj)
{
布尔匹配发现=假;
List toSearch=新列表();
List to searchnext=新列表();
添加(节点);//将主节点添加到搜索列表
而(!matchfind){
toSearch.AddRange(toSearchNext);//复制要搜索的searchnext列表
toSearchNext.Clear();
foreach(节点_toSearch中的节点){
if(node.contains(obj))//检查节点子节点中是否存在对象
return node.getChild(obj);//返回包含对象的子节点
其他的
foreach(Node.getChildren()中的Node cNode)//在子节点中找不到匹配的对象
toSearchNext.Add(cNode);//因此将每个子节点添加到要搜索的节点列表中
}
if(toSearchNext.Count==0)//未找到匹配项
返回null;
}
返回null;
}

我的问题是真的。我上面计划的方法似乎是解决整个问题的一个不错的解决方案,还是有更好的方法来实现上述操作以获得更精确的表联接。

如果我正确理解了您的要求,那么我对您解决此问题的方法表示怀疑。通常,从数据库获取特定数据的方法不多——通常只有一种方法可以获取特定数据。对于TSP类型的问题,有多种可能的解决方案,理想的解决方案基于对系统的一些约束。我认为您不会从解决方案中获得太多收益,因为您经常会发现,它们只是表联接的一个组合,可以为您提供所需的数据。

可能是这样,如果是这样,那么我的解决方案仍然可以让我动态地找到该联接,不是吗?而不是创建一个静态的邻接列表。是的,理论上是这样的。但是你考虑过你的方法的缺点吗?如果数据库模式发生更改,您必须知道何时刷新虚拟模型。如果您打算每次都创建模型,那么从长远来看,当表和字段的数量增加时会发生什么?您的解决方案可能会出现性能问题。是的,我已经想到了这一点。我的解决方案是缓存该数据库的结构,并在应用程序加载时重新扫描目标数据库。我创建了一个能够在短时间内扫描大量数据库的查询。然后,我可以将其与现有模型进行比较。并选择我需要重新加载。然而,与生成和遍历邻接列表相比,我必须衡量它的性能。
 public Node<T> findClosestObjToNode(Node<T> node, T obj)
    {
        Boolean matchFound = false;
        List<Node<T>> toSearch = new List<Node<T>>();
        List<Node<T>> toSearchNext = new List<Node<T>>();
        toSearchNext.Add(node); //add proimary node to search list

        while(!matchFound){
            toSearch.AddRange(toSearchNext); //copy the searchnext list to search
            toSearchNext.Clear();

            foreach(Node<T> _node in toSearch){
                if (node.contains(obj)) //check for existance of object in the nodes children
                    return node.getChild(obj); //return the child node that contains the object
                else
                    foreach (Node<T> cNode in node.getChildren()) //no matching object found in child nodes
                        toSearchNext.Add(cNode); //so add each child node to the list of nodes to search
            }
            if(toSearchNext.Count == 0) //no match found
                return null;
        }
        return null;
    }