表中有一个字段
AA
111.2.3
134.1.5
157.02.03
134.04.1
156.3.01


想要实现如果2个点之间的数字是1位的,就在这个数字前加0,如果2个点之间的数字是2位的,就不变。然后把点全部去掉结果如下:
AA
1110203
1340105
1570203
1340401
1560301请教各位SQL语句该如何写?

解决方案 »

  1.   

    create table AA(col varchar(20))
    insert into aa values('111.2.3')
    insert into aa values('134.1.5')
    insert into aa values('157.02.03')
    insert into aa values('134.04.1')
    insert into aa values('156.3.01')
    goselect parsename(col,3) +
           right('00'+parsename(col,2),2)+
           right('00'+parsename(col,1),2)
    from aadrop table aa/*
                         
    ---------------------
    1110203
    1340105
    1570203
    1340401
    1560301(所影响的行数为 5 行)
    */
      

  2.   

    PARSENAME
    返回对象名的指定部分。可以检索的对象部分有对象名、所有者名称、数据库名称和服务器名称。说明  PARSENAME 函数不表明所指定名称的对象是否存在,而只是返回给定对象名的指定部分。
    语法
    PARSENAME ( 'object_name' , object_piece ) 参数
    'object_name'要检索其指定部分的对象名。object_name 是 sysname 值。本参数是可选的合法对象名。如果该对象名的所有部分均符合要求,则该名称由以下四部分组成:服务器名称、数据库名称、所有者名称和对象名。object_piece要返回的对象部分。object_piece 是 int 值,可以为下列值。Value 描述 
    1 对象名 
    2 所有者名称 
    3 数据库名称 
    4 服务器名称 
    返回类型
    nchar注释
    如果符合下列条件之一,则 PARSENAME 返回 NULL 值: object_name 或 object_piece 为 NULL 值。
    发生语法错误。
    所请求的对象部分长度为 0,并且是无效的 Microsoft® SQL Server™ 标识符。零长度的对象名将导致整个合法名称无效。 
    示例
    本示例使用 PARSENAME 返回有关 pubs 数据库中 authors 表的信息。USE pubs
    SELECT PARSENAME('pubs..authors', 1) AS 'Object Name'
    SELECT PARSENAME('pubs..authors', 2) AS 'Owner Name'
    SELECT PARSENAME('pubs..authors', 3) AS 'Database Name'
    SELECT PARSENAME('pubs..authors', 4) AS 'Server Name'下面是结果集:Object Name                    
    ------------------------------ 
    authors                        (1 row(s) affected)Owner Name                     
    ------------------------------ 
    (null)                         (1 row(s) affected)Database Name                  
    ------------------------------ 
    pubs                           (1 row(s) affected)Server Name                    
    ------------------------------ 
    (null)                         (1 row(s) affected)
      

  3.   


    select parsename(col,3) +
           right('0'+parsename(col,2),2)+
           right('0'+parsename(col,1),2)
    from aa
      

  4.   

    if object_id('tb') is not null drop table tb
    go
    create table tb(col varchar(20))
    insert into tb values('111.2.3')
    insert into tb values('134.1.5')
    insert into tb values('157.02.03')
    insert into tb values('134.04.1')
    insert into tb values('156.3.01')
    goselect replace(replace(col,'.','0'),'00','0') col from tbcol
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    1110203
    1340105
    1570203
    1340401
    1560301(5 行受影响)
      

  5.   

    对不起,可能我问题没有说清楚,我重新说下,一个表AA,有个字段COL,可能很长,而且不规则
    如:
    COL
    111.2.3.
    134.1.5.
    157.02.03.
    134.04.1.3.
    156.3.01.6.08.
    123.1.3.4.
    543.02.5.06.08.
    234.2.6.7.9.
    ....
    ....想要实现如果2个点之间的数字是1位的,就在这个数字前加0,如果2个点之间的数字是2位的,就不变。然后把点全部去掉
    结果如下:
    COL
    1110203
    1340105
    1570203
    134040103
    15603010608
    123010304
    54302050608
    23402060709。

    这样可能更能表达我的需求,求教这个语句的写法,谢谢大家
      

  6.   

    特别是谢谢dawugui,对我的问题写了这么多,可我感觉我自己问题没表达清楚,所以好像还不能解决问题
      

  7.   

    use test
    go
    if object_id('test.dbo.tb') is not null drop table tb
    -- 创建数据表
    create table tb
    (
    AA varchar(30)
    )
    go
    --插入测试数据
    insert into tb select '111.2.3.'
    union all select '134.1.5.'
    union all select '157.02.03.'
    union all select '134.04.1.3.'
    union all select '156.3.01.6.08.'
    union all select '123.1.3.4.'
    union all select '543.02.5.06.08.'
    union all select '234.2.6.7.9.'
    go
    --代码实现select * from tb order by AA/*测试结果AA
    ---------------------
    111.2.3.
    123.1.3.4.
    134.04.1.3.
    134.1.5.
    156.3.01.6.08.
    157.02.03.
    234.2.6.7.9.
    543.02.5.06.08.(8 行受影响)
    */
    ;with t as(
    select AA=cast(AA as varchar(100)),num=len(AA)-len(replace(AA,'.','')) from tb
    union all
    select AA=cast(case when substring(rtrim(AA)+'.',charindex('.',AA)+2,1)='.' then stuff(AA,charindex('.',AA),1,'0')
    when substring(rtrim(AA)+'.',charindex('.',AA)+3,1)='.' then stuff(AA,charindex('.',AA),1,'') end as varchar(100)),num=num-1
    from t where num>0

    select AA=replace(AA,'.','') from t where num=1 order by AA/*测试结果AA
    ---------------------
    1110203
    123010304
    1340105
    134040103
    15603010608
    1570203
    23402060709
    54302050608(8 行受影响)
    */
      

  8.   

    ;with t as(
        select AA=cast(AA as varchar(100)),num=len(AA)-len(replace(AA,'.','')) from tb
        union all
        select AA=cast(case when substring(rtrim(AA)+'.',charindex('.',AA)+2,1)='.' then stuff(AA,charindex('.',AA),1,'0')
        when substring(rtrim(AA)+'.',charindex('.',AA)+3,1)='.' then stuff(AA,charindex('.',AA),1,'') end as varchar(100)),num=num-1
        from t where num>0

    select AA=replace(AA,'.','') from t where num=1 order by AA
    最前面的;WITH T AS是什么意思?
      

  9.   


    可以执行么??;with t as(...)在这里起到循环的作用!SQL中使用WITH AS提高性能-使用公用表表达式(CTE)简化嵌套SQL
    一.WITH AS的含义 
        WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到。有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数据的部分。 
    特别对于UNION ALL比较有用。因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,所以可以使用WITH AS短语,则只要执行一遍即可。如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。而提示materialize则是强制将WITH AS短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。
    二.使用方法
    先看下面一个嵌套的查询语句:select * from person.StateProvince where CountryRegionCode in 
             (select CountryRegionCode from person.CountryRegion where Name like 'C%')    上面的查询语句使用了一个子查询。虽然这条SQL语句并不复杂,但如果嵌套的层次过多,会使SQL语句非常难以阅读和维护。因此,也可以使用表变量的方式来解决这个问题,SQL语句如下:declare @t table(CountryRegionCode nvarchar(3))
    insert into @t(CountryRegionCode)  (select CountryRegionCode from person.CountryRegion where Name like 'C%')select * from person.StateProvince where CountryRegionCode 
                         in (select * from @t)
        虽然上面的SQL语句要比第一种方式更复杂,但却将子查询放在了表变量@t中,这样做将使SQL语句更容易维护,但又会带来另一个问题,就是性能的损失。由于表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式并不太适合数据量大且频繁查询的情况。为此,在SQL Server 2005中提供了另外一种解决方案,这就是公用表表达式(CTE),使用CTE,可以使SQL语句的可维护性,同时,CTE要比表变量的效率高得多。    下面是CTE的语法:[ WITH <common_table_expression> [ ,n ] ]
    <common_table_expression>::=
            expression_name [ ( column_name [ ,n ] ) ]
        AS
            ( CTE_query_definition )    现在使用CTE来解决上面的问题,SQL语句如下: with
    cr as
    (
        select CountryRegionCode from person.CountryRegion where Name like 'C%'
    )select * from person.StateProvince where CountryRegionCode in (select * from cr)    其中cr是一个公用表表达式,该表达式在使用上与表变量类似,只是SQL Server 2005在处理公用表表达式的方式上有所不同。    在使用CTE时应注意如下几点:
    1. CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。如下面的SQL语句将无法正常使用CTE:
    with
    cr as
    (
        select CountryRegionCode from person.CountryRegion where Name like 'C%'
    )
    select * from person.CountryRegion  -- 应将这条SQL语句去掉
    -- 使用CTE的SQL语句应紧跟在相关的CTE后面 --
    select * from person.StateProvince where CountryRegionCode in (select * from cr)
    2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示: with
    cte1 as
    (
        select * from table1 where name like 'abc%'
    ),
    cte2 as
    (
        select * from table2 where id > 20
    ),
    cte3 as
    (
        select * from table3 where price < 100
    )
    select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id3. 如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句使用的就是数据表或视图了,如下面的SQL语句所示:
    --  table1是一个实际存在的表with
    table1 as
    (
        select * from persons where age < 30
    )
    select * from table1  --  使用了名为table1的公共表表达式
    select * from table1  --  使用了名为table1的数据表4. CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。5. 不能在 CTE_query_definition 中使用以下子句:(1)COMPUTE 或 COMPUTE BY(2)ORDER BY(除非指定了 TOP 子句)(3)INTO (4)带有查询提示的 OPTION 子句(5)FOR XML(6)FOR BROWSE6. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:declare @s nvarchar(3)
    set @s = 'C%'
    ;  -- 必须加分号
    with
    t_tree as
    (
        select CountryRegionCode from person.CountryRegion where Name like @s
    )
    select * from person.StateProvince where CountryRegionCode in (select * from t_tree)    CTE除了可以简化嵌套SQL语句外,还可以进行递归调用,关于这一部分的内容将在下一篇文章中介绍。
      

  10.   

    是不是可以简单点,分步执行,我现在先写
    select AA=cast(AA as varchar(100)),num=len(AA)-len(replace(AA,'.','')) into tb1 from tb先把NUM字段加进去,然后如何再写下去?
      

  11.   

    /*if object_id('P') is not null drop table Pcreate table P
    (
    AA varchar(30)
    )insert into P 
    select '111.2.3.' union all 
    select '134.1.5.' union all 
    select '157.02.03.' union all 
    select '134.04.1.3.' union all 
    select '156.3.01.6.08.' union all 
    select '123.1.3.4.' union all 
    select '543.02.5.06.08.' union all 
    select '234.2.6.7.9.'*/with t as--用来去最后一个点
    (select (case when right(AA,1) = '.' then left(AA,len(AA)-1) else AA end) bb from P )
    select replace(replace(bb,'.','0'),'00','0') bb from t--借鉴8楼
      

  12.   

    select replace(replace(bb,'.','0'),'00','0') bb from t--借鉴8楼
    这个是不对的,因为字段内容也可能是156.13.01.6.36,这样的话就要变成1560130106036了,出错了
      

  13.   

    12楼是因为with前有东西,所以才加分号的。
      

  14.   

    把分号去掉就说WITH附近有错误。。
    能够分布实现也行,不一定要一步实现
      

  15.   


    看来你的SQL Server不支持 with CTE as试试下面 SQL Server 2000 的代码
    use test
    go
    if object_id('test.dbo.tb') is not null drop table tb
    -- 创建数据表
    create table tb
    (
    AA varchar(30)
    )
    go
    --插入测试数据
    insert into tb select '111.2.3.'
    union all select '134.1.5.'
    union all select '157.02.03.'
    union all select '134.04.1.3.'
    union all select '156.3.01.6.08.'
    union all select '123.1.3.4.'
    union all select '543.02.5.06.08.'
    union all select '234.2.6.7.9.'
    go
    --代码实现select * from tb order by AA
    /*测试结果AA
    ---------------------
    111.2.3.
    123.1.3.4.
    134.04.1.3.
    134.1.5.
    156.3.01.6.08.
    157.02.03.
    234.2.6.7.9.
    543.02.5.06.08.(8 行受影响)
    */--SQL Server 2000
    declare @t table(AA  varchar(30),num as len(AA)-len(replace(AA,'.','')))
    insert into @t(AA)
    select AA=(case when left(reverse(AA),1)='.' then stuff(AA,len(AA),1,'') else AA end) from tb
    while(select sum(num) from @t)>0
    begin
    update @t set AA=case when substring(rtrim(AA)+'.',charindex('.',AA)+2,1)='.' then stuff(AA,charindex('.',AA),1,'0')
    when substring(rtrim(AA)+'.',charindex('.',AA)+3,1)='.' then stuff(AA,charindex('.',AA),1,'') else AA end
    end
    select AA from @t order by AA
    /*
    AA
    ---------------------
    1110203
    123010304
    1340105
    134040103
    15603010608
    1570203
    23402060709
    54302050608(8 行受影响)
    */--SQL Server 2005
    ;with t as(
    select AA=cast(AA as varchar(100)),num=len(AA)-len(replace(AA,'.','')) from tb
    union all
    select AA=cast(case when substring(rtrim(AA)+'.',charindex('.',AA)+2,1)='.' then stuff(AA,charindex('.',AA),1,'0')
    when substring(rtrim(AA)+'.',charindex('.',AA)+3,1)='.' then stuff(AA,charindex('.',AA),1,'') end as varchar(100)),num=num-1
    from t where num>0

    select AA=replace(AA,'.','') from t where num=1 order by AA
    /*测试结果AA
    ---------------------
    1110203
    123010304
    1340105
    134040103
    15603010608
    1570203
    23402060709
    54302050608(8 行受影响)
    */
      

  16.   

    是的,我用的SQLSERVER2000的,我的表里还有其他的字段,我先去试一试行不行,谢谢
      

  17.   

    happycell188问你个很白痴的问题我的表中还有其他的字段,但是其他字段是不变的,比如还有字段BB,CC应该加在哪里?
      

  18.   

    --SQL Server 2000
    declare @t table(AA1  varchar(30),AA  varchar(30),num as len(AA)-len(replace(AA,'.','')))
    insert into @t(AA1,AA)
    select AA,AA=(case when left(reverse(AA),1)='.' then stuff(AA,len(AA),1,'') else AA end) from tb
    while(select sum(num) from @t)>0
    begin
    update @t set AA=case when substring(rtrim(AA)+'.',charindex('.',AA)+2,1)='.' then stuff(AA,charindex('.',AA),1,'0')
    when substring(rtrim(AA)+'.',charindex('.',AA)+3,1)='.' then stuff(AA,charindex('.',AA),1,'') else AA end
    end
    select AA1,AA from @t order by AA
    /*
    AA1 AA
    ------------------------------
    111.2.3. 1110203
    123.1.3.4. 123010304
    134.1.5. 1340105
    134.04.1.3. 134040103
    156.3.01.6.08. 15603010608
    157.02.03. 1570203
    234.2.6.7.9. 23402060709
    543.02.5.06.08. 54302050608(8 行受影响)
    */在 @t 里面加了一个标识列 AA1 ,这个列的值和原表里面的 AA 值相同!这就意味着可以通过 @t 表与原表连接来选出其他字段 BB,CC 等
      

  19.   

    终于搞明白了,太谢谢你了happycell188,感谢,感谢,感谢!