一个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")
不行!
请教大家我应该怎么查询,这是我第一次提问,有什么不当之处,希望能指正。
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")
不行!
请教大家我应该怎么查询,这是我第一次提问,有什么不当之处,希望能指正。
解决方案 »
- 为什么这样只查找到一条记录呢
- MSChart中画统计线的时候,StatLine的成员Flag的各个值代表什么含义?在线急等,请教了!!!
- 怎样使vb中的一个窗口永远在主程序窗口的前面阿,多谢高手指教
- 如何得到并修改一个WORD文档的“作者、标题”等信息?急,高分!!!
- 如何让实时数据不会中断??
- EXE窗体中Text的读取
- 多文档窗体中的窗口菜单的问题
- 如何修改一个数据库字符串字段的大小(急)
- 请教怎么查看当前类的运行状态?
- 100分求教,不够再加200-400,autolisp 如何调用vb编写的activex exe?
- 调用mediaplayer控件,怎么实现反方向的播放呢?就是倒着放??
- 问个和 进制有点关系的问题 看看咋搞合适
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条了。
谢谢,您说的方法我也考虑过,但对于数据量较大,实时性要求较高的情况下可能不是首选,在我的问题中,返回记录只是工作的很小一部分,还要进行大量数学处理才能返回给用户,而速度要求很高,所以想使用尽快的方法。当然如果实在不行,也只能手工处理,不过,不到万不得已,不用这招……
加一辅助字段,like:
01,02,04,08,11.......对应的,01,02是你code里每一个要分隔的字的起始位
sql里可以用mid的.楼主觉得呢?生成code的时候,做个额外的工作,就是填好辅助字段
谢谢,我想过的是加布尔字段来表示当前表中是否存在父亲,其实和你的想法类似,都是辅助字段,但考虑到加重更新数据的负担(它自己的Code改变了,要重设该布尔字段;表中其他记录的Code改变了,它都要检查是不是它父亲,如果是,还要看改后还是不是它父亲;每个修改、添加、删除记录的行为它都要参与,更别提批量更新了),仔细想想,难度也不小,而且处理的代码较分散,会降低程序可读性,另外明明是一个字段可以表达清楚地,尽量不用两个字段,你说呢?
如果使用的不是优化好的SQL,或者是SQL语句是最优化,还是十分复杂的,还不如弄到VB里面来处理,像你这种情况,我觉着弄到数组里面来处理还是比较方便的。
您说的是把字段内容直接读到数组里去,然后判断父子关系,最后保留满足条件的数组元素是不是?可接下来的功能需要我提供Recordset,给数组的波及面就大了,恐怕很多不是我负责的部分都要改动……
还是谢谢您,如果是我错误理解您的意思,还请指教。
该表的字段定义为
Code-----------就是那代码
Level----------级次
IsDetail-------是否为底级科目你先确认是否可以建表。然后下一步再想办法。
Level----------级次
IsDetail-------是否为底级科目
同意此方法,只是可能基础维护部分会做变动
"(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会有所变化。
&up
吃完回来看
sektor(普通动物)说对了,注意看我在7楼的说明,用你的方法,本来满足条件的“1.1”(它在表中能找到父亲:1)成了不满足条件的。要知道,不是只有最下层的记录(Code长度为6)才需要找父亲,它的上层(Code长度为3)也要找父亲。
事实上,在实际中,我并不能确定Code到底有多长,有多少级,我只能得到一个掩码(在这里我举了个例子:#.#.##)来表示最下层的Code形式,而在掩码中每一个小数点左边的部分(如第一个小数点左边的部分是:#,第二个小数点左边的部分是:#.#)都可以作为一个有效的Code在表中存在,只不过说明了级别的不同。
Level Length
1 1
2 3
3 5
4 8
1.在各个含Code字段的表中加一个文本字段,用来表示它父亲的Code(如Code为1.4.41,则该字段为1.4,当然表中是否有记录的Code是1.4就另当别论了),这样我找一条记录的父亲就容易多了,一次Select就可以了,速度很快,相当于把一步查询工作放到了平时做。代价是每次改Code都要相应改该字段,批量改也不例外。
2.允许我建临时表,分步找到满足条件的记录,但速度慢点,只是不用改现有表的结构。
感谢大家的帮助,社会主义初级阶段,分太少,见谅。
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)
SELECT * FROM T
WHERE IsAncestor(Code, '1')
AND EXISTS(SELECT * FROM T T2 WHERE T2.Code = PCode(T.Code))
谢谢,我会考虑的。