1. 程式人生 > 實用技巧 >SQL程式碼之多組織資料彙總成樹形表格展示

SQL程式碼之多組織資料彙總成樹形表格展示

需求多組織(一個數據庫例項裡面,存在一個總公司資料庫,多個分公司資料庫)環境中,以總公司的會計科目為主(分公司可能不存在總公司存在的科目),以樹形結構的方式展示各個科目下每個公司的該科目對應的餘額資料。每類科目有一個餘額彙總小計,最後再做一個全部餘額合計,本例中使用一個總公司,一個分公司做的演示

效果如下所示

準備工作:

1、在資料庫中建立兩個資料庫,一個 MyWorkTest (表示總公司) 一個MyWorkTestBackUp(表示分公司)

2、分別在兩個資料庫中執行表結構sql語句(沒用註釋的部分兩個表都需要執行,註釋的部分,只需要執行對應資料庫的sql部分)

3、準備treetable外掛

程式碼實現:

1、表結構SQL

--公司資訊
Create Table MyWorkTest_CompanyInfo(
    id int IDENTITY(1,1) NOT NULL,
    fullname nvarchar(10) NOT NULL,
    isHeader bit not null,
    dbname nvarchar(100) not null
)
GO
delete from MyWorkTest_CompanyInfo
insert into MyWorkTest_CompanyInfo(fullname,isHeader,dbname)
select '
總公司',1,'MyWorkTest' UNION ALL select '成都分公司',0,'MyWorkTestBackUp' GO --科目資訊 Create Table MyWorkTest_Atype( typeid nvarchar(50) not null, parid nvarchar(50) not null, leveal smallint not null, sonnum int not null, fullname nvarchar(66) not null, usercode nvarchar(50) not null, balance numeric(
18,2) default(0) ) GO delete from MyWorkTest_Atype /* --MyWorkTest 資料庫資料 --資產類 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00000','root','0','5','全部科目','00',0 UNION ALL select '00001','00000','1','3','資產類','10',0 UNION ALL --17640 select '0000100001','00001','2','0','庫存現金','1001',10000 UNION ALL select '0000100002','00001','2','2','銀行存款','1002',0 UNION ALL --7520 select '000010000200001','0000100002','3','0','建設銀行','100201',1020 UNION ALL select '000010000200002','0000100002','3','2','工商銀行','100202',0 UNION ALL --6500 select '00001000020000200001','000010000200002','4','0','成都工商銀行','10020201',4000 UNION ALL select '00001000020000200002','000010000200002','4','0','綿陽工商銀行','10020202',2500 UNION ALL select '0000100003','00001','2','2','其他貨幣資金','1003',0 UNION ALL --120 select '000010000300001','0000100003','3','0','外埠存款','100301',20 UNION ALL select '000010000300002','0000100003','3','0','信用卡','100302',100 --負債類 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00002','00000','1','4','負債類','20',0 UNION ALL --1073 select '0000200001','00002','2','0','短期借款','2001',10 UNION ALL select '0000200002','00002','2','2','應付賬款','2002',0 UNION ALL --33 select '000020000200001','0000200002','3','0','應付貨款','200201',11 UNION ALL select '000020000200002','0000200002','3','0','應付加工費','200202',22 UNION ALL select '0000200003','00002','2','1','應交稅費','2003',0 UNION ALL --30 select '000020000300001','0000200003','3','2','應交增值稅','200301',0 UNION ALL --30 select '00002000030000100001','000020000300001','4','0','進項稅額','20030101',10 UNION ALL select '00002000030000100002','000020000300001','4','0','己交稅金','20030102',20 UNION ALL select '0000200004','00002','2','','應付職工薪酬','2004',1000 --共同類 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00003','00000','1','1','共同類','30',0 UNION ALL --30 select '0000300001','00003','2','0','貨幣兌換','3001',10 UNION ALL select '0000300002','00003','2','0','總公司有子公司沒有的專案','3002',20 --所有者權益 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00004','00000','1','2','所有者權益','40',0 UNION ALL --350 select '0000400001','00004','2','0','實收資本','4001',150 UNION ALL select '0000400002','00004','2','0','盈餘公積','4002',200 --成本類 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00005','00000','1','1','成本類','50',0 UNION ALL --30 select '0000500001','00005','2','2','生產成本','5001',0 UNION ALL --30 select '000050000100001','0000500001','3','0','基本生產成本','500101',10 UNION ALL select '000050000100002','0000500001','3','0','輔助生產成本','500102',20 */ /* --MyWorkTestBackUp 資料庫資料 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00000','root','0','5','全部科目','00',0 UNION ALL select '00001','00000','1','3','資產類','10',176.2 UNION ALL select '0000100001','00001','2','0','庫存現金','1001',100 UNION ALL select '0000100002','00001','2','2','銀行存款','1002',75 UNION ALL select '000010000200001','0000100002','3','0','建設銀行','100201',10 UNION ALL select '000010000200002','0000100002','3','2','工商銀行','100202',65 UNION ALL select '00001000020000200001','000010000200002','4','0','成都工商銀行','10020201',40 UNION ALL select '00001000020000200002','000010000200002','4','0','綿陽工商銀行','10020202',25 UNION ALL select '0000100003','00001','2','2','其他貨幣資金','1003',1.20 UNION ALL select '000010000300001','0000100003','3','0','外埠存款','100301',0.20 UNION ALL select '000010000300002','0000100003','3','0','信用卡','100302',1 --負債類 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00002','00000','1','4','負債類','20',1.73 UNION ALL select '0000200001','00002','2','0','短期借款','2001',0.1 UNION ALL select '0000200002','00002','2','2','應付賬款','2002',0.33 UNION ALL select '000020000200001','0000200002','3','0','應付貨款','200201',0.11 UNION ALL select '000020000200002','0000200002','3','0','應付加工費','200202',0.22 UNION ALL select '0000200003','00002','2','1','應交稅費','2003',0.3 UNION ALL select '000020000300001','0000200003','3','2','應交增值稅','200301',0.3 UNION ALL select '00002000030000100001','000020000300001','4','0','進項稅額','20030101',0.1 UNION ALL select '00002000030000100002','000020000300001','4','0','己交稅金','20030102',0.2 UNION ALL select '0000200004','00002','2','','應付職工薪酬','2004',1 --共同類 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00003','00000','1','1','共同類','30',0.1 UNION ALL select '0000300001','00003','2','0','貨幣兌換','3001',0.1 --所有者權益 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00004','00000','1','2','所有者權益','40',0.35 UNION ALL select '0000400001','00004','2','0','實收資本','4001',0.15 UNION ALL select '0000400002','00004','2','0','盈餘公積','4002',0.2 --成本類 insert into MyWorkTest_Atype(typeid,parid,leveal,sonnum,fullname,usercode,balance) select '00005','00000','1','1','成本類','50',0.3 UNION ALL select '0000500001','00005','2','2','生產成本','5001',0.3 UNION ALL select '000050000100001','0000500001','3','0','基本生產成本','500101',0.1 UNION ALL select '000050000100002','0000500001','3','0','輔助生產成本','500102',0.2 */
View Code

2、儲存過程

IF EXISTS ( SELECT  *
            FROM    dbo.sysobjects
            WHERE   id = OBJECT_ID(N'[dbo].[P_Inf_GetAtypeAssistantBalance]')
                    AND OBJECTPROPERTY(id, N'IsProcedure') = 1 )
  DROP PROCEDURE [dbo].[P_Inf_GetAtypeAssistantBalance]
GO

/*
    需求:多組織環境,以總公司的科目為參考(存在總公司有的科目在子公司沒有的情況),統計每個公司的每個科目的餘額情況
    以樹形的方式顯示科目,在末級顯示各個公司該科目的餘額情況,
    每個末級科目顯示各個公司該科目餘額的彙總資料,
    不同科目類一個科目餘額小計,最後彙總一個全部餘額合計
*/
CREATE PROCEDURE P_Inf_GetAtypeAssistantBalance
AS
BEGIN
    SET NOCOUNT ON
    --變數申明
    DECLARE @ComName nvarchar(200),@DbName nvarchar(200), @IsHead bit, @Sql nvarchar(max)
    DECLARE @MaxLevel INT,@CIndex int
    DECLARE @CIndexStr nvarchar(200)

    -- 獲取末級科目
    SELECT typeid,leveal
    INTO #AtypeCw 
    FROM MyWorkTest_Atype 
    WHERE sonnum = 0 

    --末級資料表
    CREATE TABLE #FinalData(
        CompanyID nvarchar(50),
        TypeID nvarchar(200),
        ParId nvarchar(200),
        BalanceTotal numeric(18,4),
        leveal int DEFAULT 0,
        CIndex nvarchar(200)
    )
    -- 獲取末級資料封裝
    set @CIndex =1
    Declare my_cursor Cursor For Select dbname, fullname,isHeader  From MyWorkTest_CompanyInfo Where dbname <> ''  Order By isHeader Desc
    Open my_cursor
    Fetch Next From my_cursor Into @DbName, @ComName,@IsHead
    While @@Fetch_Status = 0
    BEGIN
        SET @CIndexStr = right(cast(right('0000'+rtrim(@CIndex),4) as varchar(4)),4)
        SET @SQL ='select '''+@ComName+''', a.typeid,a.parid,a.balance,a.leveal,'''+@CIndexStr+''' AS cindex  from ['+@DbName+']..MyWorkTest_Atype  a
        INNER join #AtypeCw b on a.typeid = b.typeid'
        INSERT INTO #FinalData(CompanyID,TypeID,ParId,BalanceTotal,leveal,CIndex)
        exec (@Sql) 

        INSERT INTO #FinalData(CompanyID,TypeID,ParId,BalanceTotal,leveal,CIndex)    
        SELECT @ComName AS CompanyID,A.typeid,left(A.typeid,LEN(A.typeid)- 5) AS ParId,0 as BalanceTotal,0 AS leveal,@CIndexStr AS CIndex
        FROM #AtypeCw A LEFT JOIN #FinalData B ON A.typeid = B.TypeID AND b.CompanyID = @ComName
        WHERE B.TypeID IS NULL 
        GROUP BY A.typeid
        SET @CIndex = @CIndex+1
    Fetch Next From my_cursor Into @DbName, @ComName,@IsHead
    End
    Close my_cursor
    Deallocate my_cursor
 
    --在末級增加公司資料
    select LEFT(typeid,5) as ATypeIndex, tag, usercode, fullname,typeid,parId,balancetotal ,leveal,
    ROW_NUMBER() OVER(PARTITION By LEFT(typeid,5) Order By typeid,parId,tag ) as AtypeInnerIndex
    into #LastLevealData
    from (
        select 10 tag,a.usercode, a.fullname, f.TypeID,f.ParId, sum(BalanceTotal)AS BalanceTotal,a.leveal from #FinalData  f
        left join MyWorkTest_Atype  a on f.TypeID = a.typeid
        GROUP BY f.TypeID,a.fullname,f.ParId,a.leveal,a.usercode
        UNION ALL
        select 20 tag,'' AS usercode,CompanyID,TypeID+CIndex,TypeID, SUM(BalanceTotal) AS BalanceTotal,fc.leveal from #FinalData fc
        group by CompanyID,TypeID,ParId,fc.leveal,fc.CIndex
    ) t order by TypeID,tag
   
 
   --增加父級資料            
    SELECT @MaxLevel = max(leveal) FROM #LastLevealData            
    WHILE @MaxLevel > 1
      BEGIN
        INSERT INTO #LastLevealData(ATypeIndex,tag, usercode,fullname,typeid,parId,balancetotal,leveal,AtypeInnerIndex)
        SELECT LEFT(b.typeId,5) AS ATypeIndex ,10,b.usercode,b.FullName,b.typeId,b.parid,BalanceTotal,b.leveal,'' AS AtypeInnerIndex
        FROM 
        (
          SELECT DISTINCT LEFT(typeid, LEN(typeid)-5) as typeid,
            SUM(BalanceTotal) AS BalanceTotal
          FROM #LastLevealData  
          WHERE tag = 10 AND leveal = @MaxLevel
          GROUP BY LEFT(typeid, LEN(typeid)-5)            
        ) a
        INNER JOIN MyWorkTest_Atype b ON a.typeid = b.typeid 
        SET @MaxLevel = @MaxLevel - 1
     END 

    update #LastLevealData set parid = '00000' where leveal = 2 and tag = 10  
    update #LastLevealData set leveal = 9 where leveal = 1 and tag = 10
        
    -- 獲取資料來源
    select ATypeIndex,tag,usercode, fullname,typeid,parId,balancetotal,leveal,
    ROW_NUMBER() OVER(PARTITION By LEFT(typeid,5) Order By ATypeIndex ,typeid,tag) as AtypeInnerIndex
    into #DataSource
    from #LastLevealData 
    
    --小類合計放在每一類的最後面處理開始
    select ATypeIndex,tag,usercode, fullname,typeid,parId,balancetotal,leveal,
    ROW_NUMBER() OVER(Order By ATypeIndex,leveal,AtypeInnerIndex) as AtypeInnerIndex
    into #DataSourceRst
    from #DataSource
    
    delete from #DataSource 
    insert into #DataSource
    select * from #DataSourceRst
    --小類合計放在每一類的最後面處理結束
    
    --所有合計
    insert into #DataSource(ATypeIndex,tag,usercode, fullname,typeid,parId,balancetotal,leveal,AtypeInnerIndex) 
    select '99999' AS ATypeIndex,40 AS tag, '合計' AS usercode, '合計' AS fullname,'99999' AS typeid, '00000' AS  parId,sum(balancetotal), 0 as leveal,
    0 AS  AtypeInnerIndex 
    from #DataSource where leveal = 9 
    update #DataSource set usercode = fullname+'小計' where leveal = 9
    
    select * from #DataSource order by ATypeIndex
    
  --刪除臨時表
    DROP TABLE #AtypeCw
    DROP TABLE #FinalData
    DROP TABLE #LastLevealData
    DROP TABLE #DataSource
    DROP TABLE #DataSourceRst
    
END
GO
View Code

3、頁面程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tree-table</title>
    <link rel="stylesheet" href="/Content/TreeTable/assets/layui/css/layui.css">
    <link rel="stylesheet" href="/Content/TreeTable/assets/common.css" />
</head>
<body>
    <link rel="stylesheet" href="/Content/TreeTable/assets/layui/css/layui.css">
    <link rel="stylesheet" href="/Content/TreeTable/assets/common.css" />
    <p></p>
    <div class="layui-container">
        <div class="layui-btn-group">
            <button class="layui-btn" id="btn-expand">全部展開</button>
            <button class="layui-btn" id="btn-fold">全部摺疊</button>
        </div>
        <table id="auth-table" class="layui-table" lay-filter="auth-table"></table>
    </div>
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="/Content/TreeTable/assets/layui/layui.js"></script>
    <script>
    $.ajax({
        url: '/MyTest/GetDataSource',
        type: 'post',
        dataType: 'json',
        success: function (res) {
            layui.config({
                base: '/Content/TreeTable/module/'
            }).extend({
                treetable: 'treetable-lay/treetable'
            }).use(['table', 'treetable'], function () {
                var $ = layui.jquery;
                var table = layui.table;
                var treetable = layui.treetable;
                // 渲染表格
                layer.load(2);
                treetable.render({
                    data: res.data,
                    treeColIndex: 1,
                    treeSpid: '00000',
                    treeIdName: 'TypeId',
                    treePidName: 'ParId',
                    elem: '#auth-table',
                    page: false,
                    cols: [[
                        { type: 'numbers' },
                        { field: 'UserCode', minWidth: 200, title: '科目編碼' },
                        { field: 'FullName', minWidth: 200, title: '科目名稱' },
                        { field: 'BalanceTotal', title: '餘額' },
                        { field: 'AtypeInnerIndex', width: 80, align: 'center', title: '排序號' },
                        { field: 'TypeId', width: 80, align: 'center', title: 'ID' },
                        { field: 'ParId', width: 80, align: 'center', title: '父級ID' },
                    ]],
                    done: function () {
                        layer.closeAll('loading');
                    }
                });

                $('#btn-expand').click(function () {
                    treetable.expandAll('#auth-table');
                });

                $('#btn-fold').click(function () {
                    treetable.foldAll('#auth-table');
                });
            });
        }
    })
    </script>
</body>
</html>
View Code

4、控制器程式碼

using MyWebSiteDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace MyWebSiteDemo.Controllers
{
    public class MyTestController : Controller
    {
        public ActionResult Index()
        {
           return View();
        }

        public string GetDataSource() {
            ItemDbContext itemContext = new ItemDbContext();
            List<Item> list = itemContext.Database.SqlQuery<Item>("exec P_Inf_GetAtypeAssistantBalance").ToList();
            JsonData jsonData = new JsonData();
            jsonData.data = list;
            jsonData.code = "0";
            jsonData.msg = "OK";
            jsonData.count = "67";
            StringBuilder sb = new StringBuilder();
            JavaScriptSerializer json = new JavaScriptSerializer();
            json.Serialize(jsonData, sb);
            return sb.ToString();
        }
    }

    public class JsonData {
        public List<Item> data { get; set; }
        public string code { get; set; }
        public string msg { get; set; }
        public string count { get; set; }
    }

}
View Code

5、實體程式碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyWebSiteDemo.Models
{
    public class Item
    {
        /// <summary>
        /// 大類編號
        /// </summary>
        public string AtypeIndex { get; set; }
        //標識
        public int Tag { get; set; }
        /// <summary>
        /// 編碼
        /// </summary>
        public string UserCode { get; set; }
        /// <summary>
        /// 全名
        /// </summary>
        public string FullName { get; set; }
        /// <summary>
        /// 編號
        /// </summary>
        public string TypeId { get; set; }
        /// <summary>
        /// 父級編號
        /// </summary>
        public string ParId { get; set; }
        /// <summary>
        /// 餘額
        /// </summary>
        public decimal BalanceTotal { get; set; }
        /// <summary>
        /// 級別
        /// </summary>
        public int Leveal { get; set; }
        /// <summary>
        /// 排序
        /// </summary>
        public long AtypeInnerIndex { get; set; }

    }
}
View Code

6、資料上下文

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace MyWebSiteDemo.Models
{
    public class ItemDbContext:DbContext
    {
        public ItemDbContext() : 
            base("資料庫Key") {}
    }
}
View Code

寫寫部落格,方便自己也方便有需要的人~~