2012-01-15 47 views
0

我有一個數據庫,在那裏我保存提供貸款的人的數據。貸款只能由一個人或一羣人來完成。我向你展示了我的數據庫模式的一部分。按樹形格式分組

enter image description here

「Acreditados」保持'人物角色(人)和「Creditos」(貸款),這樣一個人可以有多個貸款和一筆貸款可能由多人作出之間的關係。 'Agrupaciones'保留'acreditados'(一個已經有貸款的人)和'grupos'(按組的貸款都有一個組名)之間的關係。 最後'movimientos'保持每個人的收費和付款。

這裏的問題是如何查詢我的數據庫,以貸款(creditos)對所有付款(movimientos)進行分組,以及如果它是個人的個人貸款顯示名稱,但是如果它是組的貸款顯示名稱組?

我已經有以下查詢:

SELECT CR.id_credito, SUM(M.monto) AS Monto, SUM(M.interes) AS Interes, SUM(M.iva) AS IVA, SUM(M.capital) AS Capital, M.fecha_mov 
FROM movimientos AS M 
JOIN cargos AS C ON C.id_movimiento = M.id_movimiento 
JOIN acreditados AS A ON A.id_acreditado = M.id_acreditado 
JOIN creditos AS CR ON CR.id_credito = A.id_credito 
WHERE C.status = 0 
GROUP BY CR.id_credito, M.fecha_mov 
ORDER BY M.fecha_mov 

與此查詢我組付款的「creditos」(貸款)和日期,因爲每次支付都有不同的日期。但我該如何與'personas'(person)表一起加入以獲得貸款人的姓名,並且如果它是按組的小組名稱顯示的貸款?實際上,如果傳統查詢可能會發生這種情況,並且這種做法是在c#中創建一個三維視圖,其中組的名稱將是父項,每個人都是子節點,那麼實際上我不這麼做。個人貸款將是沒有孩子的父母節點。 任何幫助,將不勝感激,謝謝

+0

做一個「個人」貸款一組只有一個成員(默認爲成員的名字嗎?),節省了羣衆的問題,併爲您提供設施,以債權人的其他添加和刪除到「組」。相信我你不想要這個羣體/單獨的分裂,它會比這個更多的時間在你的臉上。 – 2012-01-15 18:55:35

+0

因此,您認爲在'agrupaciones'中插入個人貸款時,將組名設置爲默認成員的名稱可以解決這個問題?但是三看門人呢?如果我這樣做,我怎樣才能在三維視圖中顯示子節點中的人員信息? – 2012-01-15 19:18:48

+0

你的問題來自處理貸款的一個或多個作爲兩個不同的事情。貸款 - >小組 - >借款人。如果組中只有一個借用者,那麼您可以跳過中間節點,但這是構建樹時的子數,您的查詢將是相同的,並且與演示不可知。 – 2012-01-16 00:37:12

回答

0

我會很關心加入額外的表,可能會重複行,從而拋出所有的聚合函數。我的意思是這樣的:

假設你有兩個人附加貸款,所以你從貸款支付開始,加入貸款,然後加入屬於該貸款的人。您現在必須爲每筆貸款付款(每個人一份)記錄2條記錄,您現在必須處理這些記錄。

我會建議做的是使用外部應用程序將字段加入到您所需的內容中。如果您從未使用過外/交叉應用,只是把它作爲一個select語句的子查詢:

SELECT (SELECT TOP 1 i.someColumn FROM innerTable i WHERE i.ID = t.ID) FROM someTable AS t 

除了它的內加入本身。這意味着您可以在FROM子句中使用IN SCOPE子查詢來重新加入。事實上,這可能是你最好的選擇,爲了保持所有支付本地化爲貸款,並保留所有人/組在這個其他查詢。所以,你的查詢會是這個樣子:

SELECT CR.id_credito, SUM(M.monto) AS Monto, SUM(M.interes) AS Interes, SUM(M.iva) AS IVA, SUM(M.capital) AS Capital, M.fecha_mov, ISNULL(tg.nombre, tp.nombre) Nombre 
FROM movimientos AS M 
JOIN cargos AS C ON C.id_movimiento = M.id_movimiento 
JOIN acreditados AS A ON A.id_acreditado = M.id_acreditado 
JOIN creditos AS CR ON CR.id_credito = A.id_credito 
OUTER APPLY (SELECT TOP 1 G.nombre FROM grupos G JOIN agrupaciones AG on AG.id_grupo = G.id_grupo WHERE AG.id_acreditado = A.id_acreditado) tg 
OUTER APPLY (SELECT TOP 1 P.nombre FROM personas P WHERE P.id_persona = A.id_persona) tp 
WHERE C.status = 0 
GROUP BY CR.id_credito, M.fecha_mov, ISNULL(tg.nombre, tp.nombre) 
ORDER BY M.fecha_mov 

一件事奪去這是外適用不需要連接回表中的其餘FROM子句,因爲它已經假設您基於來自FROM子句源(表)的其餘部分的值進行查詢。此外,不要忘記別名您的APPLY查詢(在這種情況下,它是tgtp)。

編輯:剛纔注意到需要樹視圖格式。我現在就解決這個問題。

看來,無論如何,你希望每個人的所有記錄也能被返回。在這種情況下,您希望爲組內的所有人返回相同的記錄。我認爲最好的辦法是以普通加入的方式回到人員表格(而不是應用),然後按tg.nombrepersonas.nombre字段進行分組。這樣,您仍然可以獲得每個附加到貸款的人,但您也可以返回組名,以便如果有組,則可以將其用作樹中的根節點。

至於實際創建這個樹視圖,你將不得不做一些額外的工作,以實際上得到它的設置。我建議的是以可用格式獲取查詢,並使用LINQ分組將它們一起編譯。

查詢,然後將需要改變這樣: 在上面的變化而變化的線OUTER APPLY (SELECT TOP 1 P.nombre FROM personas P WHERE P.id_persona = A.id_persona) tpINNER JOIN personas P on P.id_persona = A.id_persona,改變選擇/分組從ISNULL(tg.nombre, tp.nombre) Nombretg.nombre Grupo, P.nombre Nombre。在代碼中,取回您的查詢結果後,請使用以下LINQ語句獲取查詢(假設它至少.NET 3.5):

// Assume the query results are in dtLoanPayments strongly typed datatable. 
// Also assume we have a TreeView called tvLoans 
dtLoanPayments.AsEnumerable().GroupBy(tr => tr.Grupo).ToList().ForEach(tr => 
{ 
    (tr.Key == null ? tvLoans.Nodes : tvLoans.Nodes.Add(tr.Key)).AddRange 
     (tr.Select(ti => { TreeNode tempNode = new TreeNode(ti.Nombre); tempNode.Tag = ti; return tempNode; }).ToArray()); 
}); 

再次,它真的只是取決於你如何希望他們顯示。如果你想進一步分組,那麼你需要在內部tr.Select前做另一個GroupBy,因此它會是tr.GroupBy(ti => ti.Personas).Select,你必須爲每個貸款支付記錄創建另一個TreeNode。在這些類型的情況下,請記住保持顯示和數據邏輯分離通常要容易得多。在查詢方面,只要確保你找回的數據是正確的,然後在應用程序代碼中處理格式。

編輯:要回答你的評論問題,添加一些更多的代碼。 這只是將您的項目列表轉換爲正確嵌套的TreeNode對象的問題。我想我上面的解釋可以回答這個問題,但我可以給你解釋代碼的解釋。假設你的列表被稱爲amortList和您的TreeView被稱爲tvLoans,那就試試這個:

// First, group by group name. If it's null (meaning no group), then it will just be 
// the person's name. Doing ToList() after grouping so we can do a ForEach. 
amortList.GroupBy(tr => string.IsNullOrEmpty(tr.Grupo) ? tvLoans : tvLoans.Add(tr.Grupo)).ToList() 
    .ForEach(tr => 
    // This gives us the node we'll be adding each record to as the key. Now all 
    // we need to do is add all loan records to the node, grouping by person 
    { 
     tr.Key.Nodes.AddRange(
      // Group by person's name first 
      tr.GroupBy(ti => new TreeNode(ti.Nombre)) 
       // Then transform into each node (loan payment, etc) and add to the person node. 
       .Select(ti => 
       { 
        ti.Key.Nodes.AddRange(
         ti.Select(tn => new TreeNode(/*Use whatever field here to display.*/).ToArray()); 
        return ti.Key; // Return TreeNode. 
       }).ToArray()); 
    } 

如果這仍然是混亂的,你可以做,完成同樣的事情(和更容易理解)一個foreach。

foreach(_Amortizacion amNode in amortList) 
{ 
    // Using Null Coalescing to create the node if it doesn't exist. 
    // First check if group is null. If it isn't, try to pull the node and create it if it doesn't exist. 
    TreeNodeCollection workingNode = !string.IsNullOrEmpty(amNode.Grupo) ? 
     (tvLoans.Nodes[amNode.Grupo] ?? tvLoans.Nodes.Add(amNode.Grupo)).Nodes : 
     tvLoans.Nodes; 
    // At this point, workingNode is the NodeCollection we'll be adding the person to. Creating if doesn't exist. 
    workingNode = (workingNode[amNode.Personas] ?? workingNode.Add(amNode.Personas)).Nodes; 
    // Now we're adding the actual loan record to the person Node. 
    workingNode.Add(new TreeNode(/* This is what will show up in TreeView. */) { Tag = amNode, Name = /* Specify a key here, in case you want to search. */ }); 
} 
+0

首先感謝您的幫助。我已經使用LINQ進行了查詢,並按照您的建議獲得了結果。我的結果存儲在List <_Amortizacion>中,其中_Amortizacion具有所需的字段。我如何使用LINQ來使用該列表製作樹視圖部分? – 2012-01-18 18:40:44

+0

再次加入到我的答案中,爲您提供更多選項。這一切都是在這個窗口中完成的,所以可能會出現一些語法錯誤(沒有你不應該分辨的東西)。 – SPFiredrake 2012-01-19 15:59:14

+0

完美的,很好的解釋。感謝您在此上花費一些時間。 – 2012-01-19 17:08:13

0

要回答你的問題,因爲它涉及到當前的模式,你可以使用:

  • LEFT JOIN acreditados到人物角色和agrupaciones
  • JOIN agrupaciones到grupos
  • 使用CASE語句確定nombre是否從角色或grupos拉取

至於在樹視圖中構建這個,你會想要cre吃一個遞歸查詢來提取數據。

希望這會有所幫助。

+0

但在CASE語句中計算的布爾表達式是什麼?我想是這樣選擇 '農佈雷'= \t CASE \t \t \t WHEN P.id_persona THEN P.nombres \t \t WHEN G.id_grupo THEN G.nombre \t END ,CR.id_credito ......但沒有工作 – 2012-01-17 19:38:16

+0

你會檢查NULL。 '當P.id_persona不是NULL,那麼P.nombres ........' – user1135379 2012-01-18 00:47:58