Haskell 从数据库行构建树

Haskell 从数据库行构建树,haskell,data-structures,tree,Haskell,Data Structures,Tree,我需要从数据库行构建一个树。更具体地说,我有一个包含科目表的表格 我不想递归地查询表,而是希望在一个步骤中加载所有表的信息,即包含ID和ParentID的帐户行,然后从中构建树 这样做的一个问题是帐户行没有任何顺序,即在遇到父帐户行之前,我可能会遇到子帐户行 我认为这个问题相当普遍,所以我认为可能已经有了一个haskell库 有人能帮忙吗?你在StackOverflow得到的答案的质量几乎完全取决于你提供的问题的质量。如果你想得到一个包含一些代码的答案,你应该在你的问题中提供一些代码,如果你想得

我需要从数据库行构建一个树。更具体地说,我有一个包含科目表的表格

我不想递归地查询表,而是希望在一个步骤中加载所有表的信息,即包含ID和ParentID的帐户行,然后从中构建树

这样做的一个问题是帐户行没有任何顺序,即在遇到父帐户行之前,我可能会遇到子帐户行

我认为这个问题相当普遍,所以我认为可能已经有了一个haskell库


有人能帮忙吗?

你在StackOverflow得到的答案的质量几乎完全取决于你提供的问题的质量。如果你想得到一个包含一些代码的答案,你应该在你的问题中提供一些代码,如果你想得到一个关于某个特定库的答案,然后参考它

目前您的问题非常模糊,我只能回答您需要使用类结构来首先累积中间结果,然后通过查询这个中间数据结构来重新排列它们。正如文档所示,它的大多数访问器函数的复杂性是
O(logn)
,这是非常有效的


您不应该期望任何数据库库都提供这种功能,因为问题太具体了。

正如Nikita所说,您真正的问题是什么

您不提供任何数据类型、树键分类等

无论如何,这段代码可以帮助你思考你的问题

data Tree a = Node a [Tree a] deriving Show

db = [(0, 1)
     ,(1, 2)
     ,(1, 3)
     ,(2, 4)
     ,(2, 6)
     ,(3, 5)
     ]

rootTree = Node 0 []

insert parent child (Node key childs) =
  Node key $ if key == parent then Node child []:childs
                              else map (insert parent child) childs

insertFromDB rows = foldl insertRow rootTree rows
  where insertRow tree (parent, child) = insert parent child tree
如果无法获得有序数据,可以通过搜索父节点对其进行排序,下一个函数计算每个节点的深层次(使用相同的
db
数据)

使用
calculateDeepLevel
可以从无序且无根(无0节点)版本的
db
计算有序的
db
版本和基于0的版本

import qualified Data.Map as M
import qualified Data.Tree as T
import Data.List (foldl')
import Control.Arrow ((&&&))
import Data.Maybe (fromMaybe)
接下来,假设我们有一个id和一个可选的父id(根节点没有父节点)的记录,并带有一些值:

data Rec a = Rec { recId       :: Int
                 , recParentId :: Maybe Int
                 , recValue    :: a
                 }
没有什么可以阻止多个节点具有父id,因此我们可能会找到多个树,因此我们将列表转换为树的函数可能如下所示:

toTree :: [Rec a] -> [T.Tree a]
toTree rs = ts where
首先,让我们构建一个从可选父id到具有该父id的记录列表的映射:

    -- gs :: M.Map (Maybe Int) [Rec a]
    gs = foldl' f M.empty rs where
        f m r = M.insertWith (const (r:)) (recParentId r) [r] m
接下来,让我们从一个虚拟根节点开始展开一棵树,它的子节点将是我们感兴趣的树的根。请注意,虚拟根节点没有值,因此我们使用
未定义

    -- t :: T.Tree a
    t = T.unfoldTree mkNode (undefined, Nothing)
mkNode
函数被传递我们想要构建的节点的值和id。它使用前面构造的
Map
返回值和子值/id对的列表:

    -- mkNode :: (a, Maybe Int) -> (a, [(a, Maybe Int)])
    mkNode (a, i) = (a, map (recValue &&& Just . recId)
                          . fromMaybe []
                          . M.lookup i $ gs)
最后,我们可以丢弃伪根节点,并将其直接子节点作为我们感兴趣的树的根返回:

    ts = T.subForest t
下面是一个测试:

main = mapM_ (putStrLn . T.drawTree)
         $ toTree [ Rec 0 Nothing "rootA"
                  , Rec 1 (Just 0) "rootA.childA"
                  , Rec 2 (Just 0) "rootA.childB"
                  , Rec 3 (Just 1) "rootA.childA.childA"
                  , Rec 4 (Just 1) "rootA.childA.childB"
                  , Rec 5 (Just 2) "rootA.childB.childA"
                  , Rec 6 (Just 2) "rootA.childB.childB"
                  , Rec 7 Nothing "rootB"
                  , Rec 8 (Just 7) "rootB.childA"
                  , Rec 9 (Just 7) "rootB.childB"
                  , Rec 10 (Just 8) "rootB.childA.childA"
                  , Rec 11 (Just 8) "rootB.childA.childB"
                  , Rec 12 (Just 9) "rootB.childB.childA"
                  , Rec 13 (Just 9) "rootB.childB.childB"
                  ]
由此产生:

rootB
|
+- rootB.childB
|  |
|  +- rootB.childB.childB
|  |
|  `- rootB.childB.childA
|
`- rootB.childA
   |
   +- rootB.childA.childB
   |
   `- rootB.childA.childA

rootA
|
+- rootA.childB
|  |
|  +- rootA.childB.childB
|  |
|  `- rootA.childB.childA
|
`- rootA.childA
   |
   +- rootA.childA.childB
   |
   `- rootA.childA.childA

这是哪个数据库?博士后?Mysql?神谕我认为它使用SQL是错误的吗?数据库是mysql。除非mysql发生了很大的变化,否则我认为它不能为我提供一个层次结构的结果,也就是说,树和递归地查询数据库是可行的,但这将是相当昂贵的。我无法提供代码或数据结构作为示例,因为数据结构尚未完成。不过,您在示例中提供的数据结构足以解释一般原理。上面的例子可以很好地构建树,但只有在输入数据有序的情况下,我可能无法从数据库中检索到某些东西。我刚刚试过你的代码,效果很好,但当我恢复列表时,它无法构建树。因此,我试图找出当元素以随机顺序出现时如何构建树。我添加了
calculateDeepLevel
以获得节点级别,使用它,您可以使用
sortBy
进行排序。
rootB
|
+- rootB.childB
|  |
|  +- rootB.childB.childB
|  |
|  `- rootB.childB.childA
|
`- rootB.childA
   |
   +- rootB.childA.childB
   |
   `- rootB.childA.childA

rootA
|
+- rootA.childB
|  |
|  +- rootA.childB.childB
|  |
|  `- rootA.childB.childA
|
`- rootA.childA
   |
   +- rootA.childA.childB
   |
   `- rootA.childA.childA