表结构(类别表)
ParentKindID,KindId,Kind
-1           1      路基工程
 1           2      涵洞 
 2           3      盖板涵
 3           4      箱涵
 4           5      圆管涵
 1           6      路基土石方
-1           7      路面工程
项目表
KindID ItemID Item
费用表
ID(自增长) ItemID Total
如何才能得到如下统计结构 路基工程  涵洞          盖板涵    Item1
 路基工程  涵洞          箱涵      Item2
 路基工程  涵洞          圆管涵    Item3
 路基工程  路基土石方              Item4
 路面工程  。。总之,根据项目表反推出前面的类别列,前面三列(类别列)可能只有一列,可能两列,三列甚至更多,怎样才能得到如此结构

解决方案 »

  1.   

    给你一个示例:
    /*
     1。实现级联查询 例如,提供一个员工编号,能够查询出该
     员工的上级和间接上级的信息。
     2。实现级联查询 例如,提供一个员工编号,能够查询出该
     员工的下级和间接下级的信息。
     3。实现级联删除。例如,指定一个员工编号,当删除该员工
     的基本信息的时候,该员工的所有下级全部被删除。无论
     上级还是下级,都包括员工自己。
     4。实现级联更新。当一个员工的工号改变时,所有以该员工
     为直接上级的员工的reportto字段的值都变为新的工号。
    */
    
    create table emp(
        eid int primary key,
        ename varchar(20),
        sal money,
        reportto int references emp(eid)   --该员工的直接上级
        )
    --drop table emp
        insert into emp select 1001,'rain',1000,null
        union select 1002,'ann',3000,1001
        union select 1003,'lopez',2000,1001
        union select 1004,'nakata',3000,1002
        union select 1005,'tae',1500,1004
        union select 1006,'raul',900,1004
        union select 1007,'owen',15000,1006
    --select * from emp
    /*实现级联查询 例如,提供一个员工编号,能够查询出该员工的上级和间接上级的信息。*/
    create proc p1 @eid int 
    as
    begin
     declare @re table(eid int,level int)
     declare @l int
     set @l=0
     insert @re select @eid,@l
     while @@rowcount>0
     --全局变量@@rowcount,记录上次操作影响的行数 
     begin
     set @l=@l+1
     insert @re select a.reportto,@l from emp as a,@re as b where a.eid=b.eid and b.level=@l-1
     --循环将当前记录的直接上级插入@re
     end
     select a.* from @re as b inner join emp as a on a.eid = b.eid
    end
    --drop proc p1
    exec p1 1005
    
    /*实现级联查询 例如,提供一个员工编号,能够查询出该员工的下级和间接下级的信息。*/
    create proc p2 @eid int 
        as
        begin
         declare @re table(eid int,level int)
         declare @l int
         set @l=0
         insert @re select @eid,@l
         while @@rowcount>0
         --全局变量@@rowcount,记录上次操作影响的行数
         begin
         set @l=@l+1
         insert @re select a.eid,@l from emp as a,@re as b where a.reportto=b.eid and b.level=@l-1
         --循环将当前记录的直接下级插入@re
         end
         select a.* from @re as b inner join emp as a on a.eid = b.eid
         end
         --drop proc p2
         exec p2 1004
    
    
      

  2.   

    关于数据库设计中的分级分层问题的总结(适用于组织结构图及家谱等问题) 大家在很多地方都会遇到诸如此类的问题,如:
    在一个组织中,从高层领导到中层领导到普通职工,有着一种分级的关系,这些关系在关系型数据库中表示时,有它特别的方法。
    有些人把它们分别建立在不同的表中,建立相应的关系,这虽然是一种解决办法,但如果在应用中,它会给软件带来诸多不便,特别是程序健壮性方法,如果此时需要多加一个职位,这种解决办法就需要多加一张表,那此时对应用程序的改动将可想而知。
    我在此处提供的方法并不是什么独特的方法,而是大家所属知的方法,但在我们的论坛上经常有人问到并且我再三进行解答。
    因此我一方面将这些帖的问题收集一下,再加上全面的解释,组织成这样一篇文章,希望对大家有所帮助。
    如有不正确之处请大家提出意见。问题一:
    想设计一个组织结构管理的数据库模型,能让用户自由定义组织结构层次和关系,大家有没有好的意见和经典的结构模型?解决:
    其实一个层次的模型在关系数据库本身就是个问题。根本问题在于关系模型的第一范式就要求属性分为不可再分,这样的话就直接造成层次结构实现的复杂性。如果一个属性可以包含多个内容的话,那就可以有这样一个属性,叫做"下级"的属性,它包含了此成员的所有下级,但这样是不可取的。
    虽然这样,但组织结构这个问题比较容易解决。原因是组织结构本身的结构比较简单。
    在设计的时候只要做一个指向本身主键的属性,也就是说这个属性的外键就是本表的主键,在查询的时候很简单,只要做一个自连接就可以了,也就是
    select b.* from (t1) as a,(t1) as b where a.p1=b.p2 and a.p1="bill"
    t1为表,p1为主键,p2为下属,它指向它的上级p1。上面这条语句查询的就是bill的下属名单。
    select a.* from (t1) as a,(t1) as b where a.p1=b.p2 and b.p2="bill"
    这条语句查询的就是bill的上级,这就实现了多层。问题二:
    如何在数据库中表示这样的数据,希望在论坛中,做出把一些人加入黑名单的功能,描述:
    这个数据库保存每个用户所讨厌的用户,例如:
    mary tom john
    sam joe
    以上表示mary讨厌tom和john, sam讨厌joe解决:
    这在关系代数里是一个自连接多对多关系数据库,ER图不便画出,在这里我只说明解决方案。
    当然有一个注册用户表,如:
    CREATE TABLE [TB_user] (
    [userid] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
    [username] [varchar] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    CONSTRAINT [PK_TB_user] PRIMARY KEY  CLUSTERED 
    (
    [userid]
    )  ON [PRIMARY] 
    ) ON [PRIMARY]
    GO
    再来就是保存讨厌对象的表:
    CREATE TABLE [bedfriend] (
    [bedid] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
    [userid1] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
    [userid2] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
    CONSTRAINT [PK_bedfriend] PRIMARY KEY  CLUSTERED 
    (
    [bedid]
    )  ON [PRIMARY] 
    ) ON [PRIMARY]
    GOOK了,TB_user里存的是注册用户
    bedfrend表里存的是如下信息:
    bedfrend
    ---------------------
    bedid    userid1    userid2
    1          1           2
    2          1           5
    3          1           8
    4          2           3
    5          2           4
    6          3           6注意有一点,就是,这个关系设计的是如果bill讨厌kate,那kate不一定讨厌bill
    原因大家都知道,kate喜欢bill嘛,bill喜欢nana
    问题三:
    用户表:uid[用户ID],depid[所属部门ID]
    部门表:depid[部门ID],pdepid[上级部门ID]函数:UidInDepSub(depid int,uid int) --判断uid是否属于depid[部门ID]或其下级部门ID。
    结果:select * from news where dbo.UidInDepSub(depid,uid)>1 --可以用于select中判断,此处需要多层递归判断,层次不定。请问此函数应该怎么写?解决:
    CREATE TABLE [depart] (
     [depid] [int] NOT NULL ,
     [pdepid] [int] NULL ,
     CONSTRAINT [PK_depart] PRIMARY KEY  CLUSTERED 
     (
      [depid]
     )  ON [PRIMARY] ,
     CONSTRAINT [FK_depart_depart] FOREIGN KEY 
     (
      [pdepid]
     ) REFERENCES [depart] (
      [depid]
     )
    ) ON [PRIMARY]--向depart加入数据
    insert into depart values(1,null)--顶层的上级一定要为null
    insert into depart values(2,1)
    insert into depart values(3,1)
    insert into depart values(4,2)
    insert into depart values(5,2)
    insert into depart values(6,3)
    insert into depart values(7,4)
    insert into depart values(8,4)
    insert into depart values(9,5)
    insert into depart values(10,6)
    create function billfun(@departid int,@uid int)
    returns int
    as
    begin
     declare @temp int
     SELECT @temp=pdepid
     FROM dbo.depart
     WHERE (depid = @uid)
     if(@temp=@departid)
      RETURN 1
     if(@temp is null)
      RETURN 0
     RETURN (dbo.billfun(@departid,@temp))
    end
    select dbo.billfun(2,8)
    --为1
    select dbo.billfun(3,8)
    --为0上面的函数是一个递归函数,楼主当时看我的程序短还以为不能用呢。其实它就是一直递归查询uid是不是属于它们的高n级部门,而非高一级部门。
    这是我blog上的,你可以自己到上面来看。
    http://blog.csdn.net/geniusli/archive/2006/03/16/626155.aspx