id       classname  parentid  path 
1 新闻    0    0,1
2 国内新闻    1    0,1,2
3 国际新闻    1    0,1,3
4 北京    2    0,1,2,4
8 湖北    2    0,1,2,8
11 汕尾    2    0,1,2,11
12 娱乐    0    0,12刚才看到有介绍这种无限分类,
不过后面的path在插入的时候怎么知道自己的id号是多少。
谢谢

解决方案 »

  1.   

    --> 生成测试数据表: [tb]
    IF OBJECT_ID('[tb]') IS NOT NULL
    DROP TABLE [tb]
    GO
    CREATE TABLE [tb] ([id] [int],[name] [nvarchar](10),[pid] [int])
    INSERT INTO [tb]
    SELECT '1','新闻','0' UNION ALL
    SELECT '2','国内新闻','1' UNION ALL
    SELECT '3','国际新闻','1' UNION ALL
    SELECT '4','北京','2' UNION ALL
    SELECT '8','湖北','2' UNION ALL
    SELECT '11','汕尾','2' UNION ALL
    SELECT '12','娱乐','0'--SELECT * FROM [tb]-->SQL查询如下:;WITH T AS
    (
    SELECT *,lvl=0,px=CAST(id AS VARBINARY(MAX)) FROM [tb] WHERE pid=0
    UNION ALL
    SELECT A.*,lvl+1,px+CAST(A.id AS VARBINARY) FROM tb A,T WHERE A.pid=T.id
    )
    SELECT replicate('.',lvl)+ltrim(lvl) AS lvl,id,name,pid 
    FROM T
    ORDER BY px
    /*
    lvl        id          name       pid
    ---------- ----------- ---------- -----------
    0          1           新闻         0
    .1         2           国内新闻       1
    ..2        4           北京         2
    ..2        8           湖北         2
    ..2        11          汕尾         2
    .1         3           国际新闻       1
    0          12          娱乐         0(7 行受影响)
    */通过类似这样查询出来可以吗
      

  2.   

    --> 生成测试数据表: [tb]
    IF OBJECT_ID('[tb]') IS NOT NULL
    DROP TABLE [tb]
    GO
    CREATE TABLE [tb] ([id] [int],[name] [nvarchar](10),[pid] [int])
    INSERT INTO [tb]
    SELECT '1','新闻','0' UNION ALL
    SELECT '2','国内新闻','1' UNION ALL
    SELECT '3','国际新闻','1' UNION ALL
    SELECT '4','北京','2' UNION ALL
    SELECT '8','湖北','2' UNION ALL
    SELECT '11','汕尾','2' UNION ALL
    SELECT '12','娱乐','0'--SELECT * FROM [tb]-->SQL查询如下:;WITH T AS
    (
    SELECT *,lvl=0,px=CAST(id AS varbinary(MAX)),
    Path=CAST(LTRIM(pid)+','+LTRIM(id) AS varchar(max)) 
    FROM [tb] WHERE pid=0
    UNION ALL
    SELECT A.*,lvl+1,px+CAST(A.id AS varbinary),
    Path+','+LTRIM(a.id) 
    FROM tb A,T 
    WHERE A.pid=T.id
    )
    SELECT REPLICATE('.',lvl)+LTRIM(lvl) AS lvl,id,name,pid,Path 
    FROM T
    ORDER BY px
    /*
    lvl        id          name       pid         Path
    ---------- ----------- ---------- ----------- ----------
    0          1           新闻         0           0,1
    .1         2           国内新闻       1           0,1,2
    ..2        4           北京         2           0,1,2,4
    ..2        8           湖北         2           0,1,2,8
    ..2        11          汕尾         2           0,1,2,11
    .1         3           国际新闻       1           0,1,3
    0          12          娱乐         0           0,12(7 行受影响)
    */这是加上显示Path后的效果
      

  3.   

    htl258的sql真厉害,不过运行的工作量会变多了吗?
      

  4.   


    如果层次不是很多,如几十层,SQL还是很轻松的。
      

  5.   

    这是典型的树形结构存储。可以用触发器实现插入/更新/删除时自动调整Path的值。
      

  6.   

    插入时不知道id,可以先插入,然后通过scope_identity()获取id值,然后再更新