一个MDB数据库,用DAO3.61操作,其中一个表“T”有一个文本型字段“Code”,其中的数据是以“.”分隔的数字如:1、1.1、1.2、1.1.01、1.1.14、1.2.05、1.4.41,可以看到形式#、#.#、#.#.##都是合法的格式,用来表示该记录与其他记录的从属关系,如“1.1”是“1”的儿子,同时是“1.1.01”和“1.1.14”的父亲。而“1.4.41”找不到相应的父亲“1.4”,则说明他是孤儿(注意虽然存在“1”,但没有直接的父亲,仍是孤儿)。现在要做的是:根据用户提供的Code(只能是#或#.#,而不能是#.#.##,也就是说不能是最下层的Code),如“1”,查找并返回它所有的子孙(孤儿不算,如“1.4.41”)。用Select查询后再筛选或嵌套查询都可以,只要能返回满足条件的记录集就可以了(只读的也行)。我想用嵌套查询,思路是看表“T”中的每一个Code是否可以找到父亲,如果可以,同时满足“Code Like 用户提供的Code & ".*"”的条件就返回,可是Split和InstrRev都不让用在SQL里面。
Set Rs = DB.OpenRecordset("SELECT * FROM T AS T1 WHERE Code Like '" & Code & ".*' AND (SELECT Count(*) FROM T WHERE Code.T = Left(Code.T1,Len(Code.T1)-Len(Split(Code.T1," & chr(34) & "." & chr(34) & ")(Ubound(Split(Code.T1," & chr(34) & "." & chr(34) & "))))-1)) > 0 ORDER BY Code")
不行!
请教大家我应该怎么查询,这是我第一次提问,有什么不当之处,希望能指正。

解决方案 »

  1.   

    你是想一个SQl查出每一行数据是否都有父亲么?
      

  2.   

    to zyguyue(何必何苦) 
    1.最好是一条SQL语句就可以查出表中存在父亲的记录。
    2.表中也有可能存在“1.4.41”,却并不存在它的父亲“1.4”,所以通过本条记录中是否有点只能知道它应不应该有个父亲(像“1”是没点的,也就不应该有父亲了),但不知道表中是否真实存在它的父亲(有可能过去有,但被删除了)。
    3.我可能描述的还不够清楚。问题简单点说,应该是在表中查找每条记录的Code,然后看表中是不是还能找到它的父亲,如果找到父亲(假设父亲的代码是Code2),才是满足条件的记录(应该返回Code的记录,而不是Code2的记录)。如顶楼说的情况,存在7条记录,Code分别是:
    1
    1.1
    1.2
    1.1.01
    1.1.14
    1.2.05
    1.4.41
    那么查询的结果应该是除去“1”和“1.4.41”以外的其他5条记录,因为“1”没点,肯定没父亲;而“1.4.41”的父亲应该是“1.4”,但表中的7条记录中没有“1.4”,所以它没找到父亲,就不符合条件。
    4.我在顶楼描述的情况算是更进一步,要求返回的记录中再根据用户的要求来筛选,用户输入“1.1”,那么就返回Like 1.1.*的记录,这个问题是小事,很简单,大家主要是看上面3条,我就卡在上面3条了。
      

  3.   

    To jtkk()
    谢谢,您说的方法我也考虑过,但对于数据量较大,实时性要求较高的情况下可能不是首选,在我的问题中,返回记录只是工作的很小一部分,还要进行大量数学处理才能返回给用户,而速度要求很高,所以想使用尽快的方法。当然如果实在不行,也只能手工处理,不过,不到万不得已,不用这招……
      

  4.   

    仔细看了一下,个人感觉不太容易实现.你要在mdb,你还要一条语句.那么,是否要考虑为这个字段加上一个辅助字段呢?我第一想到的就是:
    加一辅助字段,like:
    01,02,04,08,11.......对应的,01,02是你code里每一个要分隔的字的起始位
    sql里可以用mid的.楼主觉得呢?生成code的时候,做个额外的工作,就是填好辅助字段
      

  5.   

    To sektor(普通动物)
    谢谢,我想过的是加布尔字段来表示当前表中是否存在父亲,其实和你的想法类似,都是辅助字段,但考虑到加重更新数据的负担(它自己的Code改变了,要重设该布尔字段;表中其他记录的Code改变了,它都要检查是不是它父亲,如果是,还要看改后还是不是它父亲;每个修改、添加、删除记录的行为它都要参与,更别提批量更新了),仔细想想,难度也不小,而且处理的代码较分散,会降低程序可读性,另外明明是一个字段可以表达清楚地,尽量不用两个字段,你说呢?
      

  6.   

    //谢谢,您说的方法我也考虑过,但对于数据量较大,实时性要求较高的情况下可能不是首选,在我的问题中,返回记录只是工作的很小一部分,还要进行大量数学处理才能返回给用户,而速度要求很高,所以想使用尽快的方法。当然如果实在不行,也只能手工处理,不过,不到万不得已,不用这招……
    如果使用的不是优化好的SQL,或者是SQL语句是最优化,还是十分复杂的,还不如弄到VB里面来处理,像你这种情况,我觉着弄到数组里面来处理还是比较方便的。
      

  7.   

    To jjkk168(老加班的人--每日要顶二十贴)
    您说的是把字段内容直接读到数组里去,然后判断父子关系,最后保留满足条件的数组元素是不是?可接下来的功能需要我提供Recordset,给数组的波及面就大了,恐怕很多不是我负责的部分都要改动……
    还是谢谢您,如果是我错误理解您的意思,还请指教。
      

  8.   

    如果实在需要用Recordset,一条SQL语句似乎没有办法解决。如果能够加一个表那似乎好办一点
    该表的字段定义为
    Code-----------就是那代码
    Level----------级次
    IsDetail-------是否为底级科目你先确认是否可以建表。然后下一步再想办法。
      

  9.   

    Code-----------就是那代码
    Level----------级次
    IsDetail-------是否为底级科目
    同意此方法,只是可能基础维护部分会做变动
      

  10.   

    用一个查询就能完成的:Set Rs = DB.OpenRecordset( "SELECT * FROM T AS T1 WHERE (LEN(Code) > 3) AND " & _
      "(LEFT(Code,3) IN (SELECT Code FROM T WHERE (Code LIKE '" & Code & "%')))")
    在SQL SERVER上调试通过, 测试时使用的SQL语句是:
    SELECT *
      FROM T
      WHERE (LEN(Code) > 3)
        AND (LEFT(Code, 3) IN (SELECT Code FROM T WHERE (Code LIKE '1%')))或者
    SELECT *
      FROM T
      WHERE (LEN(Code) > 3)
        AND (LEFT(Code, 3) IN (SELECT Code FROM T WHERE (Code LIKE '1.1%')))ACCESS上没有测试,具体的SQL会有所变化。
      

  11.   

    第一感觉楼上理解错了意思.
    &up
    吃完回来看
      

  12.   

    To jadeluo(秀峰)
    sektor(普通动物)说对了,注意看我在7楼的说明,用你的方法,本来满足条件的“1.1”(它在表中能找到父亲:1)成了不满足条件的。要知道,不是只有最下层的记录(Code长度为6)才需要找父亲,它的上层(Code长度为3)也要找父亲。
    事实上,在实际中,我并不能确定Code到底有多长,有多少级,我只能得到一个掩码(在这里我举了个例子:#.#.##)来表示最下层的Code形式,而在掩码中每一个小数点左边的部分(如第一个小数点左边的部分是:#,第二个小数点左边的部分是:#.#)都可以作为一个有效的Code在表中存在,只不过说明了级别的不同。
      

  13.   

    写着写着卡住了,楼主有没有一个级次定义表?必须是这样的
    Level Length
    1       1
    2       3
    3       5
    4       8
      

  14.   

    目前向项目负责人提出了两种方案:
    1.在各个含Code字段的表中加一个文本字段,用来表示它父亲的Code(如Code为1.4.41,则该字段为1.4,当然表中是否有记录的Code是1.4就另当别论了),这样我找一条记录的父亲就容易多了,一次Select就可以了,速度很快,相当于把一步查询工作放到了平时做。代价是每次改Code都要相应改该字段,批量改也不例外。
    2.允许我建临时表,分步找到满足条件的记录,但速度慢点,只是不用改现有表的结构。
    感谢大家的帮助,社会主义初级阶段,分太少,见谅。
      

  15.   

    既然是用 Access 数据库,在 Access 的模块中定义两个个函数
    Public Functin PCode(byval Code As String) As String
    根据"." 分割规则求上级编码
    Public Function IsAncestor(byval Code as string,byval ACode as string) as boolean
    判断是否为祖先SQL 如下
    SELECT * FROM T
      WHERE IsAncestor(Code, '1')
       AND EXISTS(SELECT * FROM T T2 WHERE PCode(T2.Code) = T.Code)
      

  16.   

    更正 SQL
    SELECT * FROM T
      WHERE IsAncestor(Code, '1')
       AND EXISTS(SELECT * FROM T T2 WHERE T2.Code = PCode(T.Code))
      

  17.   

    To Tiger_Zhao(VB老鸟)
    谢谢,我会考虑的。