sql高手请进,排序问题

popcat007 2009-07-27 11:37:16
有个表,有这样两个字段a varchar,b int
数据如下:
a b
10 null
10.1 1
10.1.1 null
10.1.2 null
10.1.3 null
10.1.4 null
10.2 0
10.3 2
10.4 3
10.5 4

现在要实现排序的结果
a b
10 null
10.2 0
10.1 1
10.1.1 null
10.1.2 null
10.1.3 null
10.1.4 null
10.3 2
10.4 3
10.5 4
如何实现,在线等
...全文
175 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
仙道彰 2009-07-27
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 popcat007 的回复:]
那总该给个地址吧,不给地址我还不是大海捞针
[/Quote]
那你就大海捞石头
popcat007 2009-07-27
  • 打赏
  • 举报
回复
那总该给个地址吧,不给地址我还不是大海捞针
-狙击手- 2009-07-27
  • 打赏
  • 举报
回复
这个以前讨论过,你看看
popcat007 2009-07-27
  • 打赏
  • 举报
回复
那个排序在b字段为null的时候,按照a排序,在b不为null的时候,同级字段按照b排序,就是给他加了个下级字段才不会排了
jiangshun 2009-07-27
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jinjazz 的回复:]
..
没啥规律
[/Quote]
up
jinjazz 2009-07-27
  • 打赏
  • 举报
回复
..
没啥规律
fcuandy 2009-07-27
  • 打赏
  • 举报
回复
看错题意了。

楼主需要说明两点:
1,每个.后的位数是否确定
2, .的个数是否固定。


啥破设定,只允许连续回三次。只能贴这了。


if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([a] varchar(6),[b] int)
insert [tb]

select '10.1',1 union all
select '10.1.1',null union all
select '10.1.2',null union all
select '10.1.3',null union all
select '10.1.4',null union all
select '10.2',0 union all
select '10.3',2 union all
select '10.4',3 union all
select '10.5',4 union all
select '10',null
go


select * from tb a
order by
isnull(isnull(b,(
select top 1 b from tb b where a.a like a+'.%'
and not exists(select 1 from tb where a.a like a+'.%' and len(a)>len(b.a))
)),0),isnull((
select top 1 a from tb b where a.a like a+'.%'
and not exists(select 1 from tb where a.a like a+'.%' and len(a)>len(b.a))
),'')

/*
10 NULL
10.2 0
10.1 1
10.1.1 NULL
10.1.2 NULL
10.1.3 NULL
10.1.4 NULL
10.3 2
10.4 3
10.5 4


*/
fcuandy 2009-07-27
  • 打赏
  • 举报
回复
如果每个.前后的数字的位数不定,要注意补位。
fcuandy 2009-07-27
  • 打赏
  • 举报
回复
if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([a] varchar(6),[b] int)
insert [tb]

select '10.1',1 union all
select '10.1.1',null union all
select '10.1.2',null union all
select '10.1.3',null union all
select '10.1.4',null union all
select '10.2',0 union all
select '10.3',2 union all
select '10.4',3 union all
select '10.5',4 union all
select '10',null
go


select * from tb a
order by
isnull((
select top 1 a from tb b where a + '.' like a.a+'%'
and not exists(select 1 from tb where a+'.' like a.a+'%' and len(a)<len(b.a))
),'')

/*
10 NULL
10.1 1
10.1.1 NULL
10.1.2 NULL
10.1.3 NULL
10.1.4 NULL
10.2 0
10.3 2
10.4 3
10.5 4

*/
popcat007 2009-07-27
  • 打赏
  • 举报
回复
8楼的貌似是oracle的方法吧
popcat007 2009-07-27
  • 打赏
  • 举报
回复
有sqlseerver2000下的解决方案没?真不好意思,大家都给出了答案了,才发现,那个sql2005的解决方案在2000下出错了
等不到来世 2009-07-27
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 guguda2008 的回复:]
引用 7 楼 szx1999 的回复:
SQL code--sql2005:ifobject_id('[tb]')isnotnulldroptable[tb]gocreatetable[tb]([a]varchar(6),[b]int)insert[tb]select'10',nullunionallselect'10.1',1unionallselect'10.1.1',nullunionallselect'10.1.2',nullunionallselect'10.1.3',nullunionallselect'10.1.4',nullunionallselect'10.2',0unionallselect'10.3',2unionallselect'10.4',3unionallselect'10.5',4go--select * from [tb]
;with t1as
(select a,b,lvl=len(a)-len(replace(a,'.',''))from tb)
,t2as
(select a,b,p=cast(isnull(b,9999)asvarchar(8000)),lvlfrom t1where lvl=0unionallselect a.a,a.b,b.p+rtrim(isnull(a.b,9999)),a.lvlfrom t1 ajoin t2 bon a.alike b.a+'.%'and a.lvl=b.lvl+1
)select a,bfrom t2orderby p,a/*
a      b
------ -----------
10    NULL
10.2  0
10.1  1
10.1.1 NULL
10.1.2 NULL
10.1.3 NULL
10.1.4 NULL
10.3  2
10.4  3
10.5  4

(10 行受影响)*/

你用我那个测试数据就不对了,10.7在10.6在上边
[/Quote]
10.7之所以在10.6上面,是因为它对应的b为5,而10.6对应的b为null.

我的算法是同级中为null的排最后,不知LZ的本意是如何。
guguda2008 2009-07-27
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 fredrickhu 的回复:]
引用 8 楼 guguda2008 的回复:
SQL codeDECLARE@TTABLE(
AVARCHAR(10),
BINT
)INSERTINTO@TSELECT'10'      ,nullUNIONALLSELECT'10.1'    ,1UNIONALLSELECT'10.1.1'  ,nullUNIONALLSELECT'10.1.2'  ,nullUNIONALLSELECT'10.1.3'  ,nullUNIONALLSE¡­


小伙不错
[/Quote]
我会骄傲的。。。。
guguda2008 2009-07-27
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 szx1999 的回复:]
SQL code--sql2005:ifobject_id('[tb]')isnotnulldroptable[tb]gocreatetable[tb]([a]varchar(6),[b]int)insert[tb]select'10',nullunionallselect'10.1',1unionallselect'10.1.1',nullunionallselect'10.1.2',nullunionallselect'10.1.3',nullunionallselect'10.1.4',nullunionallselect'10.2',0unionallselect'10.3',2unionallselect'10.4',3unionallselect'10.5',4go--select * from [tb]
;with t1as
(select a,b,lvl=len(a)-len(replace(a,'.',''))from tb)
,t2as
(select a,b,p=cast(isnull(b,9999)asvarchar(8000)),lvlfrom t1where lvl=0unionallselect a.a,a.b,b.p+rtrim(isnull(a.b,9999)),a.lvlfrom t1 ajoin t2 bon a.alike b.a+'.%'and a.lvl=b.lvl+1
)select a,bfrom t2orderby p,a/*
a b
------ -----------
10 NULL
10.2 0
10.1 1
10.1.1 NULL
10.1.2 NULL
10.1.3 NULL
10.1.4 NULL
10.3 2
10.4 3
10.5 4

(10 行受影响)*/
[/Quote]
你用我那个测试数据就不对了,10.7在10.6在上边
--小F-- 2009-07-27
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 guguda2008 的回复:]
SQL codeDECLARE@TTABLE(
AVARCHAR(10),
BINT
)INSERTINTO@TSELECT'10' ,nullUNIONALLSELECT'10.1' ,1UNIONALLSELECT'10.1.1' ,nullUNIONALLSELECT'10.1.2' ,nullUNIONALLSELECT'10.1.3' ,nullUNIONALLSE¡­
[/Quote]

小伙不错
guguda2008 2009-07-27
  • 打赏
  • 举报
回复

DECLARE @T TABLE(
A VARCHAR(10),
B INT
)
INSERT INTO @T
SELECT '10' ,null UNION ALL
SELECT '10.1' ,1 UNION ALL
SELECT '10.1.1' ,null UNION ALL
SELECT '10.1.2' ,null UNION ALL
SELECT '10.1.3' ,null UNION ALL
SELECT '10.1.4' ,null UNION ALL
SELECT '10.2' ,0 UNION ALL
SELECT '10.3' ,2 UNION ALL
SELECT '10.4' ,3 UNION ALL
SELECT '10.7' ,5 UNION ALL
SELECT '10.6' ,NULL UNION ALL
SELECT '10.5' ,4
CREATE TABLE TEMP (
ID INT,
A VARCHAR(10),
B INT
)
INSERT INTO TEMP
SELECT ROW_NUMBER() OVER (
ORDER BY
CASE WHEN CONVERT(VARCHAR(10),B) IS NULL THEN A ELSE CONVERT(VARCHAR(10),B) END
),A,B FROM @T
ORDER BY
CASE WHEN CONVERT(VARCHAR(10),B) IS NULL THEN A ELSE CONVERT(VARCHAR(10),B) END
--SELECT * FROM TEMP

UPDATE TEMP SET ID=
CASE WHEN EXISTS(
SELECT DISTINCT 1 FROM TEMP t2 WHERE T2.A>TEMP.A
AND (LEN(T2.A)-LEN(REPLACE(T2.A,'.','')))>(LEN(TEMP.A)-LEN(REPLACE(TEMP.A,'.','')))
) THEN (SELECT MIN(T3.ID)-1 FROM TEMP t3 WHERE T3.A>TEMP.A )
WHEN EXISTS(
SELECT DISTINCT 1 FROM TEMP t2 WHERE T2.A<TEMP.A
AND (LEN(T2.A)-LEN(REPLACE(T2.A,'.','')))>(LEN(TEMP.A)-LEN(REPLACE(TEMP.A,'.','')))
) THEN (SELECT MAX(T3.ID)+1 FROM TEMP t3 WHERE T3.A<TEMP.A )
ELSE
ID
END
WHERE B IS NULL


SELECT A,B FROM TEMP ORDER BY ID,B
DROP TABLE TEMP

--吃完饭回来竟然还没人贴答案,那就我来
/*
10 NULL
10.2 0
10.1 1
10.1.1 NULL
10.1.2 NULL
10.1.3 NULL
10.1.4 NULL
10.3 2
10.4 3
10.5 4
10.6 NULL
10.7 5
*/

等不到来世 2009-07-27
  • 打赏
  • 举报
回复

--sql2005:
if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([a] varchar(6),[b] int)
insert [tb]
select '10',null union all
select '10.1',1 union all
select '10.1.1',null union all
select '10.1.2',null union all
select '10.1.3',null union all
select '10.1.4',null union all
select '10.2',0 union all
select '10.3',2 union all
select '10.4',3 union all
select '10.5',4
go
--select * from [tb]

;with t1 as
(select a,b,lvl=len(a)-len(replace(a,'.','')) from tb)
,t2 as
(
select a,b,p=cast(isnull(b,9999) as varchar(8000)),lvl from t1 where lvl=0
union all
select a.a,a.b,b.p+rtrim(isnull(a.b,9999)),a.lvl from t1 a join t2 b
on a.a like b.a+'.%' and a.lvl=b.lvl+1
)
select a,b from t2 order by p,a
/*
a b
------ -----------
10 NULL
10.2 0
10.1 1
10.1.1 NULL
10.1.2 NULL
10.1.3 NULL
10.1.4 NULL
10.3 2
10.4 3
10.5 4

(10 行受影响)
*/

22,294

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧