1001
1001011201
120101
120102
120102011300
1400
140001取得最末级:
100101
120101
12010201
1300
140001

解决方案 »

  1.   

    ----------------------------------------------------------------
    -- Author  :fredrickhu(小F,向高手学习)
    -- Date    :2011-09-27 14:12:08
    -- Verstion:
    --      Microsoft SQL Server 2008 R2 (RTM) - 10.50.1617.0 (Intel X86) 
    -- Apr 22 2011 11:57:00 
    -- Copyright (c) Microsoft Corporation
    -- Enterprise Evaluation Edition on Windows NT 6.1 <X64> (Build 7600: ) (WOW64)
    --
    ----------------------------------------------------------------
    --> 测试数据:[tb]
    if object_id('[tb]') is not null drop table [tb]
    go 
    create table [tb]([col] int)
    insert [tb]
    select 1001 union all
    select 100101 union all
    select 1201 union all
    select 120101 union all
    select 120102 union all
    select 12010201 union all
    select 1300 union all
    select 1400 union all
    select 140001
    --------------开始查询--------------------------
    select * from [tb] t where LEN(col)=(select MAX(len(col)) from tb where LEFT(col,4)=LEFT(t.col,4))
    ----------------结果----------------------------
    /* col
    -----------
    100101
    12010201
    1300
    140001(4 行受影响)
    */
      

  2.   

    ----------------------------------------------------------------
    -- Author  :fredrickhu(小F,向高手学习)
    -- Date    :2011-09-27 14:12:08
    -- Verstion:
    --      Microsoft SQL Server 2008 R2 (RTM) - 10.50.1617.0 (Intel X86) 
    -- Apr 22 2011 11:57:00 
    -- Copyright (c) Microsoft Corporation
    -- Enterprise Evaluation Edition on Windows NT 6.1 <X64> (Build 7600: ) (WOW64)
    --
    ----------------------------------------------------------------
    --> 测试数据:[tb]
    if object_id('[tb]') is not null drop table [tb]
    go 
    create table [tb]([col] int)
    insert [tb]
    select 1001 union all
    select 100101 union all
    select 1201 union all
    select 120101 union all
    select 120102 union all
    select 12010201 union all
    select 1300 union all
    select 1400 union all
    select 140001
    --------------开始查询--------------------------
    select * from [tb] t where LEN(col)=(select MAX(len(col)) from tb where CHARINDEX(ltrim(t.col),ltrim(col))>0)
    ----------------结果----------------------------
    /*col
    -----------
    100101
    120101
    12010201
    1300
    140001(5 行受影响)
    */
      

  3.   

    如果是oracle数据库呢?
    还有编号规则是4-2-2,或者4-3-3呢
      

  4.   

    if object_id('[tb]') is not null drop table [tb]
    go 
    create table [tb]([col] NVARCHAR(500))
    insert [tb]
    select 1001 union all
    select 100101 union all
    select 1201 union all
    select 120101 union all
    select 120102 union all
    select 12010201 union all
    select 1300 union all
    select 1400 union all
    select 140001
    SELECT * FROM TB AS a WHERE NOT EXISTS(SELECT 1 FROM TB WHERE Col LIKE a.Col||'_%')
      

  5.   

    ----------------------------------------------------------------
    -- Author  :qiudf(day day up)
    -- Date    :2011-09-27 15:10
    -- Verstion:
    ----------------------------------------------------------------
    --> 测试数据:[a]with a as
    (
    select 1001 a01 from dual union all
    select 100101  from dual  union all
    select 1201  from dual union all
    select 120101 from dual  union all
    select 120102  from dual union all
    select 120103  from dual union all
    select 120104  from dual union all
    select 12010201  from dual union all
    select 1300  from dual union all
    select 130004 from dual union all
    select 130005  from dual union all
    select 13000401  from dual union all
    select 1400  from dual
    )
    --根据树的层级来抓取
    select a01 from
    (
    select a01,level rr,row_number() over(partition by substr(a01,1,length(a01)-2) order by a01) rn
     from a
    where length(a01)>2
    start with a01=substr(a01,1,4) connect by substr(a01,1,length(a01)-2)=prior a01
    )
    where rn<rr
    union all
    --考虑单行的情况
    select to_number(a01)
    from
      (select substr(a01,1,4) a01,max(rn) rn
      from 
        (select a01,row_number() over(partition by  substr(a01,1,4) order by a01) rn from a)
        group by substr(a01,1,4)
      )
    where rn=1--result:
    1 100101
    2 120101
    3 12010201
    4 130004
    5 13000401
    6 1400
      

  6.   

    如果是:4-3-3

    substr(a01,1,length(a01)-2)
    改为
    substr(a01,1,length(a01)-3)
    即可!
      

  7.   

    楼主参考上面的大牛,功力不凡。具体有这种查询需求,是否要考虑自己的数据库设计的不合理
    一般对于树形结构,我们要有一下几个关键字段:
    ParentID,FullID,Level,IsLeaf
    这样的话,我们查询明细节点的话,直接判断是否为叶子节点即可。
      

  8.   

    fredrickhu、roy_88的sql,应该是对的。这个是财务软件的会计科目表。
    如果设置parentid、fullid、level、IsLeaf冗余字段,
    好处:查询科目信息快,不用动态计算这些值。
    缺点:维护这些信息时,需要额外的判断、保存代码。会计科目基础表,数量不多,
    一般只是200多条记录,动态法查询也不会太慢,所以省略了这些字段。但是如果换成是产品配套清单BOM,数据可能多达上万时,
    就需要上述冗余字段了。所以不同情况,不同的设计方法。
      

  9.   

    bz_acc是表,acc_code是字段。
    数据如下:
    5405
    5501
    550101
    550102
    550201
    550202
    55020221
    550203
    550205
    550206
    550207
    550208
    550209
    550211
    550215
    550216
    550217
    550218
    550220
    5503
    550301
    550302
    550303
    550304
    5601
    560101
    560102
    560103
    560104
    560106
    5701
    5801
    1701
    5301
    1102
    113319
    1911
    217105
    312104
    410506
    1101
    113301
    113315
    1221
    1500
    1505
    111102
    1151
    140201
    210101
    21710107
    217109
    560105
    218157
    218163
    311105
    314102
    400003
    1601
    1603
    1605
    1001
    1002
    100201
    1009
    100901
    110102
    1111
    111101
    1121
    1122
    1131
    1133
    113302
    1141
    1161
    1201
    1211
    1231
    1232
    1241
    1243
    1244
    1250
    1251
    1261
    1271
    1281
    1291
    129101
    129102
    1401
    140101
    140102
    1402
    140202
    1501
    1502
    1801
    1805
    1815
    191101
    191102
    2101
    210102
    210104
    2111
    2121
    2131
    2141
    2151
    2153
    2161
    2171
    217101
    21710101
    21710102
    21710103
    21710104
    21710105
    21710106
    21710108
    21710109
    217102
    217103
    217104
    217106
    217107
    217108
    217110
    217111
    217112
    2176
    2181
    218101
    218120
    5502
    550204
    550210
    550219
    550305
    219103
    2201
    230101
    230102
    100101
    3103
    3111
    311101
    311102
    311103
    311104
    311106
    311107
    3121
    312101
    312102
    312103
    312105
    312106
    3131
    3141
    314101
    314103
    314104
    314105
    314106
    314107
    314108
    314109
    314110
    314111
    314115
    4000
    400001
    400002
    4105
    410501
    410502
    410503
    410504
    5101
    5102
    510201
    510202
    510203
    5201
    5203
    530101
    530102
    530103
    5401SELECT a.acc_code, a.* 
    FROM bz_acc  a 
    WHERE NOT EXISTS(
    SELECT 1 FROM bz_acc 
    WHERE acc_code 
    LIKE a.acc_code||'_%')
    order by a.acc_code;select acc_code, t.* from bz_acc t 
    where length(acc_code)=
    (select MAX(length(acc_code)) 
    from bz_acc 
    where instr(acc_code, t.acc_code) >0)
    order by t.acc_code;SELECT a.acc_code, a.* 
    FROM bz_acc  a 
    order by a.acc_code;发现fredrickhu的算法,结果比roy_88少2条,
    所以fredrickhu的算法,不对,而roy_88是对的。
    可以拿上面的数据来测试。
      

  10.   

    如果是已知的表,直接根据id 不是都可以查到了吗?
    如果是未知的
    select id from 表名 这样可以提高查询速度
    然后,可以根据最后一个id不是可以查到最后一行数据了吗?
      

  11.   

    ----------------------------------------------------------------
    -- Author  :qiudf(day day up)
    -- Date    :2011-09-27 15:10
    -- Verstion:
    ----------------------------------------------------------------
    --> 测试数据:[a]--create table a (a01 int)
    --select * from a for update
    --根据树的层级来抓取
    select a01 from
    (
    select a01,level rr,row_number() over(partition by substr(a01,1,length(a01)-2) order by a01) rn
     from a
    where length(a01)>2
    start with a01=substr(a01,1,length(a01))   --修改此处的取值,测试OK!
    connect by substr(a01,1,length(a01)-2)=prior a01
    )
    where rn<rr
    union all
    --考虑单行的情况
    select to_number(a01)
    from
      (select substr(a01,1,4) a01,max(rn) rn
      from 
        (select a01,row_number() over(partition by substr(a01,1,4)  order by a01) rn from a)
        group by substr(a01,1,4)
      )
    where rn=1
      

  12.   

    cosio你的sql太复杂了。
    --对的。
    SELECT t.acc_code, t.* 
    FROM bz_acc t 
    WHERE NOT EXISTS(
      SELECT * FROM bz_acc 
      WHERE acc_code LIKE t.acc_code||'_%'
      )
    order by t.acc_code;--原来是错的。修改后正确。
    select acc_code, t.* from bz_acc t 
    where length(acc_code)=(
    select MAX(length(acc_code)) 
    from bz_acc
    where instr(acc_code, t.acc_code) =1
    --where instr(acc_code, t.acc_code-) >0 --会包含不是首位开始而漏掉,故注释
    )
    order by t.acc_code;SELECT a.acc_code, a.* 
    FROM bz_acc  a 
    order by a.acc_code;
      

  13.   

    1102 1102
    1121 1121
    1122 1122
    1131 1131
    1141 1141
    1151 1151
    1161 1161
    1201 1201
    1211 1211
    1221 1221
    1231 1231
    1232 1232
    1241 1241
    1243 1243
    1244 1244
    1250 1250
    1251 1251
    1261 1261
    1271 1271
    1281 1281
    1500 1500
    1501 1501
    1502 1502
    1505 1505
    1601 1601
    1603 1603
    1605 1605
    1701 1701
    1801 1801
    1805 1805
    1815 1815
    2111 2111
    2121 2121
    2131 2131
    2141 2141
    2151 2151
    2153 2153
    2161 2161
    2176 2176
    2201 2201
    3103 3103
    3131 3131
    5101 5101
    5201 5201
    5203 5203
    5401 5401
    5405 5405
    5701 5701
    5801 5801
    100101 100101
    100201 100201
    100901 100901
    110102 110102
    111101 111101
    111102 111102
    113301 113301
    113302 113302
    113315 113315
    113319 113319
    129101 129101
    129102 129102
    140101 140101
    140102 140102
    140201 140201
    140202 140202
    191101 191101
    191102 191102
    210101 210101
    210102 210102
    210104 210104
    217102 217102
    217103 217103
    217104 217104
    217105 217105
    217106 217106
    217107 217107
    217108 217108
    217109 217109
    217110 217110
    217111 217111
    217112 217112
    218101 218101
    218120 218120
    218157 218157
    218163 218163
    219103 219103
    230101 230101
    230102 230102
    311101 311101
    311102 311102
    311103 311103
    311104 311104
    311105 311105
    311106 311106
    311107 311107
    312101 312101
    312102 312102
    312103 312103
    312104 312104
    312105 312105
    312106 312106
    314101 314101
    314102 314102
    314103 314103
    314104 314104
    314105 314105
    314106 314106
    314107 314107
    314108 314108
    314109 314109
    314110 314110
    314111 314111
    314115 314115
    400001 400001
    400002 400002
    400003 400003
    410501 410501
    410502 410502
    410503 410503
    410504 410504
    410506 410506
    510201 510201
    510202 510202
    510203 510203
    530101 530101
    530102 530102
    530103 530103
    550101 550101
    550102 550102
    550201 550201
    550203 550203
    550204 550204
    550205 550205
    550206 550206
    550207 550207
    550208 550208
    550209 550209
    550210 550210
    550211 550211
    550215 550215
    550216 550216
    550217 550217
    550218 550218
    550219 550219
    550220 550220
    550301 550301
    550302 550302
    550303 550303
    550304 550304
    550305 550305
    560101 560101
    560102 560102
    560103 560103
    560104 560104
    560105 560105
    560106 560106
    21710101 21710101
    21710102 21710102
    21710103 21710103
    21710104 21710104
    21710105 21710105
    21710106 21710106
    21710107 21710107
    21710108 21710108
    21710109 21710109
    55020221 55020221
    上面的SQL运行出来的效果,取一部分,21710101 21710101
    21710102 21710102
    21710103 21710103
    21710104 21710104
    21710105 21710105
    21710106 21710106
    21710107 21710107
    21710108 21710108
    21710109 21710109
    这些数据,末级只抓取一个嘛?
    1001
    1001011201
    120101
    120102
    120102011300
    1400
    140001取得最末级:
    100101
    120101
    12010201
    1300
    140001
    看一下需求中:  120102没有抓取!  所以.....
      

  14.   


    cosio,佩服你的钻研,但你要学习大牛,自己多动动脑筋、多看看书。