• Sql中的递归问题思考与建议


    Sql中的递归问题

    【递归】
    是一种循环方式或规则
    树的遍历常常用到
    优点:编写程序方便
    缺点:限制与内存,容易崩溃

    【描述】
    类别表
    CID,CName,FID
    FID=0表示此节点为根节点

    如何在Sql中应用递归思想

    【实践】
    实践来分析和建议:
    Exec P_IOSaveCategoryInfo 0 ,'Computer' ,0;--return 1

    Exec P_IOSaveCategoryInfo 0 ,'CPU' ,1;--return 2
    Exec P_IOSaveCategoryInfo 0 ,'Mainboard' ,1;-- return 3
    Exec P_IOSaveCategoryInfo 0 ,'Memory' ,1;-- return 4
    Exec P_IOSaveCategoryInfo 0 ,'HardDisk' ,1;-- return 5
    Exec P_IOSaveCategoryInfo 0 ,'Mouse' ,1;-- return 6
    Exec P_IOSaveCategoryInfo 0 ,'Keyboard' ,1;-- return 7
    Exec P_IOSaveCategoryInfo 0 ,'ExtendDevice' ,1;-- return 8

    Exec P_IOSaveCategoryInfo 0 ,'UsbDisk' ,8;-- return 9
    Exec P_IOSaveCategoryInfo 0 ,'SDCard' ,8;-- return 10
    Exec P_IOSaveCategoryInfo 0 ,'TFCard' ,8;-- return 11

    树的效果图如下:
    1
    |
    --------------------------------------------------
    | | | | | | |
    2 3 4 5 6 7 8
    |
    -----------------
    | | |
    9 10 11

    查询一:
    根据输入ID获取到此ID和以及旗下的子ID信息
    Select     
        [CID],
        [CatName],
        [FID],
        case when 0 = fid  then cid else fid end as nfid
    FROM   TB
    Where Cid = 1 Or FID = 1
    Order by nfid ,[FID],[CID];

    输出如下:
    CID CatName FID nfid
    ----------- ------------------------- ----------- -----------
    1 Computer 0 1
    2 CPU 1 1
    3 Mainboard 1 1
    4 Memory 1 1
    5 HardDisk 1 1
    6 Mouse 1 1
    7 Keyboard 1 1
    8 ExtendDevice 1 1

    由上可见:每次只能取2级数据

    查询二:
    尝试取3级数据
    Select A.CID ,A.CatName ,B.CID As CID1 ,B.CatName As CatName1 ,Case When C.CID is null Then B.CID Else C.CID End AS CID2 ,Case When C.CID is null Then B.CatName Else C.CatName End AS CatName2
    FROM TB A With(Nolock)
    Left Join TB B With(Nolock) On B.FID = A.CID
    Left Join TB C With(Nolock) On C.FID = B.CID
    Where A.CID = 1

    输出数据如下:
    CID CatName CID1 CatName1 CID2 CatName2
    ----------- --------------- ----------- ---------------- ----------- ---------------
    1 Computer 2 CPU 2 CPU
    1 Computer 3 Mainboard 3 Mainboard
    1 Computer 4 Memory 4 Memory
    1 Computer 5 HardDisk 5 HardDisk
    1 Computer 6 Mouse 6 Mouse
    1 Computer 7 Keyboard 7 Keyboard
    1 Computer 8 ExtendDevice 9 UsbDisk
    1 Computer 8 ExtendDevice 10 SDCard
    1 Computer 8 ExtendDevice 11 TFCard

    由上可见:前两列为一级,中两列为二级,后两列为三级,其中为Null的数据均由其父节点填充

    但问题也出现了,不方便查询使用,仅浏览而已。

    个人认为:
    看来无限级的提取,在Sql语句中也难一次性获取。
    建议:
    类似此表结构,提取最好采用两级提取(提取本身信息以及子节点信息),业务层处理数据展示关系
    特殊需求,如2-4级也可以采用查询二的方式提取,一次性提取所有节点


    回到一句老话:见机行事

    说到这里,有一点设计的思考可以考虑:
    为表新增一个字段,采用varchar,保存父子关系,

    1,Computer,0,1,10001
    2,CPU,1,1,10001-10002
    3,Mainboard,1,1,10001-10003
    4,Memory,1,1,10001-10004
    5,HardDisk,1,1,10001-10005
    6,Mouse,1,1,10001-10006
    7,Keyboard,1,1,10001-10007
    8,ExtendDevice,1,1,10001-10008
    9,UsbDisk,8,8,10001-10008-10009
    10,SDCard,8,8,10001-10008-10010
    11,TFCard,8,8,10001-10008-10011

    最后一列,为父子关系图,其中由于长度过于短小不利于定位和查询,特为数据加了10000

    这类实现,好处在于一次性提取所有关系数据。缺点,不利于修改关系。适合码表数据的定义,若动态定义此类数据需要谨慎使用。

  • 相关阅读:
    深入Java虚拟机(4)——网络移动性
    安装ftp碰到的问题及解决方法
    6.设置ListView的Item的高度无效
    hdu1181(变形课)
    ZooKeeper分布式集群部署及问题
    管理线程之创建线程
    Linux系统编程——多线程实现多任务
    Request.Params用法,后台接收httpget参数
    resharper警告 :linq replace with single call to FirstOrDefault
    SQL Prompt几个快捷键
  • 原文地址:https://www.cnblogs.com/GoGoagg/p/1897744.html
Copyright © 2020-2023  润新知