请大家帮帮忙,一个对我来说很棘手的问题

时间:2021-11-15 08:57:45
源数据来自于视图v_card_no,如下:
product_name      card_no
100元充值卡       19906000001
100元充值卡       19906000002
100元充值卡       19906000003
100元充值卡       19906000007
100元充值卡       19906000008
100元充值卡       19906000009
50元充值卡        19908000002
50元充值卡        19908000003
50元充值卡        19908000004
50元充值卡        19908000011
50元充值卡        19908000012
50元充值卡        19908000013
数据经过处理后应该得到如下结果:
product_name      from_card_no        to_card_no
100元充值卡       19906000001         19906000003
100元充值卡       19906000007         19906000009
50 元充值卡       19908000002         19906000004
50 元充值卡       19908000011         19906000013

昨晚写了一百多行的存储过程没得到想要的数据,只好请大家帮帮忙,谢谢!

14 个解决方案

#1


得到数据的依据是???

#2


就是计算号段,从结果数据里面就可以看出来,把连续的一段卡号找出来

#3


select product_name
       ,min(card_no) as from_card_no
       ,max(card_no) as to_card_no
from t 
group by product_name

#4


create table #t(p varchar(20),c varchar(11))
insert #t select '100元充值卡',       '19906000001'
    union select '100元充值卡',       '19906000002'
    union select '100元充值卡',       '19906000003'
    union select '100元充值卡',       '19906000007'
    union select '100元充值卡',       '19906000008'
    union select '100元充值卡',       '19906000009'
    union select '50元充值卡',        '19908000002'
    union select '50元充值卡',        '19908000003'
    union select '50元充值卡',        '19908000004'
    union select '50元充值卡',        '19908000011'
    union select '50元充值卡',        '19908000012'
    union select '50元充值卡',        '19908000013'

select a.p,a.c,id=identity(int,1,1) into #t0
from #t a left join #t b on a.p=b.p and a.c=cast(cast(b.c as bigint)+1 as varchar(11))
where b.p is null
order by a.p,a.c

select a.p,a.c,id=identity(int,1,1) into #t1
from #t a left join #t b on a.p=b.p and a.c=cast(cast(b.c as bigint)-1 as varchar(11)) 
where b.p is null
order by a.p,a.c

select a.p,a.c as cFrom,b.c as cTo from #t0 a join #t1 b on a.id=b.id

drop table #t,#t0,#t1

#5


上面不对 没看清结果要求

#6


--查询
select product_name,from_card_no=card_no
,to_card_no=(
select min(card_no) from v_card_no aa
where product_name=a.product_name
and card_no>a.card_no
and not exists(
select * from v_card_no
where product_name=aa.product_name
and card_no=aa.card_no+1))
from v_card_no a
where not exists(
select * from v_card_no
where product_name=a.product_name
and card_no=a.card_no-1)

#7


--示例

--示例数据
create table v_card_no(product_name varchar(20),card_no decimal(18,0))
insert v_card_no select '100元充值卡',19906000001
union  all       select '100元充值卡',19906000002
union  all       select '100元充值卡',19906000003
union  all       select '100元充值卡',19906000007
union  all       select '100元充值卡',19906000008
union  all       select '100元充值卡',19906000009
union  all       select '50元充值卡' ,19908000002
union  all       select '50元充值卡' ,19908000003
union  all       select '50元充值卡' ,19908000004
union  all       select '50元充值卡' ,19908000011
union  all       select '50元充值卡' ,19908000012
union  all       select '50元充值卡' ,19908000013
go

--查询
select product_name,from_card_no=card_no
,to_card_no=(
select min(card_no) from v_card_no aa
where product_name=a.product_name
and card_no>a.card_no
and not exists(
select * from v_card_no
where product_name=aa.product_name
and card_no=aa.card_no+1))
from v_card_no a
where not exists(
select * from v_card_no
where product_name=a.product_name
and card_no=a.card_no-1)
go

--删除测试
drop table v_card_no

/*--测试结果

product_name         from_card_no         to_card_no           
-------------------- -------------------- -------------------- 
100元充值卡              19906000001          19906000003
100元充值卡              19906000007          19906000009
50元充值卡               19908000002          19908000004
50元充值卡               19908000011          19908000013

(所影响的行数为 4 行)
--*/

#8


这么多啊,谢谢各位,我先试试行不行

#9


还有一个问题就是这个表的数据一般都有几十万上百万数据,还要考虑性能问题,本来在代码里面已经实现了,但是速度太慢,所以放到数据库库端处理

#10


刚才测试了一下,表数据不到12万,用时1分零7秒,这个查询能不能再优化一下,事实上我的问题还不只这么简单,这个视图v_card_no是建立在三个表上,在比较卡号的过程中还要把前面几位去掉,这里只是列出了11位的卡号,还有十八位的卡号,这也是数据库没设计好吧,卡号应该分两个字段存放的,因为比较卡号都是比较后面6位或者7位,要是比较11或者18位的卡号的话,肯定不能直接比较

#11


--建立表格
create table v_card_no(product_name varchar(20),card_no decimal(18,0))
--测试数据
insert v_card_no select '100元充值卡',19906000001
union  all       select '100元充值卡',19906000002
union  all       select '100元充值卡',19906000003
union  all       select '100元充值卡',19906000007
union  all       select '100元充值卡',19906000008
union  all       select '100元充值卡',19906000009
union  all       select '50元充值卡' ,19908000002
union  all       select '50元充值卡' ,19908000003
union  all       select '50元充值卡' ,19908000004
union  all       select '50元充值卡' ,19908000011
union  all       select '50元充值卡' ,19908000012
union  all       select '50元充值卡' ,19908000013
go

--处理
select v_card_no.*,identity(decimal,1,1) as row_id ,inc = '00000000000' 
into #temp 
from v_card_no 

update #temp set inc = convert(varchar(11),card_no) - row_id

select product_name,
min(card_no) as from_card_no,
max(card_no) as to_card_no 
from #temp 
group by product_name,inc

/*结果
product_name    from_card_no    to_card_no
-------------------------------------------------
100元充值卡 19906000001 19906000003
100元充值卡 19906000007 19906000009
50元充值卡 19908000002 19908000004
50元充值卡 19908000011 19908000013
-------------------------------------------------
*/


#12


各位写的Sql代码都很经典,谢谢!用临时表的确要快很多,只花了40多秒

#13


数据量大的话,临时表是最优的

#14


刚开始的思维方式太死了,只想到把数据一条一条取出来处理, chj733(八神苍月) 的这种方法很好,时间主要是花在向临时表插数据上,下次查询只要直接查询临时表就行了;zjcxc(邹建) 的方法技巧性太强了,看了都头晕

#1


得到数据的依据是???

#2


就是计算号段,从结果数据里面就可以看出来,把连续的一段卡号找出来

#3


select product_name
       ,min(card_no) as from_card_no
       ,max(card_no) as to_card_no
from t 
group by product_name

#4


create table #t(p varchar(20),c varchar(11))
insert #t select '100元充值卡',       '19906000001'
    union select '100元充值卡',       '19906000002'
    union select '100元充值卡',       '19906000003'
    union select '100元充值卡',       '19906000007'
    union select '100元充值卡',       '19906000008'
    union select '100元充值卡',       '19906000009'
    union select '50元充值卡',        '19908000002'
    union select '50元充值卡',        '19908000003'
    union select '50元充值卡',        '19908000004'
    union select '50元充值卡',        '19908000011'
    union select '50元充值卡',        '19908000012'
    union select '50元充值卡',        '19908000013'

select a.p,a.c,id=identity(int,1,1) into #t0
from #t a left join #t b on a.p=b.p and a.c=cast(cast(b.c as bigint)+1 as varchar(11))
where b.p is null
order by a.p,a.c

select a.p,a.c,id=identity(int,1,1) into #t1
from #t a left join #t b on a.p=b.p and a.c=cast(cast(b.c as bigint)-1 as varchar(11)) 
where b.p is null
order by a.p,a.c

select a.p,a.c as cFrom,b.c as cTo from #t0 a join #t1 b on a.id=b.id

drop table #t,#t0,#t1

#5


上面不对 没看清结果要求

#6


--查询
select product_name,from_card_no=card_no
,to_card_no=(
select min(card_no) from v_card_no aa
where product_name=a.product_name
and card_no>a.card_no
and not exists(
select * from v_card_no
where product_name=aa.product_name
and card_no=aa.card_no+1))
from v_card_no a
where not exists(
select * from v_card_no
where product_name=a.product_name
and card_no=a.card_no-1)

#7


--示例

--示例数据
create table v_card_no(product_name varchar(20),card_no decimal(18,0))
insert v_card_no select '100元充值卡',19906000001
union  all       select '100元充值卡',19906000002
union  all       select '100元充值卡',19906000003
union  all       select '100元充值卡',19906000007
union  all       select '100元充值卡',19906000008
union  all       select '100元充值卡',19906000009
union  all       select '50元充值卡' ,19908000002
union  all       select '50元充值卡' ,19908000003
union  all       select '50元充值卡' ,19908000004
union  all       select '50元充值卡' ,19908000011
union  all       select '50元充值卡' ,19908000012
union  all       select '50元充值卡' ,19908000013
go

--查询
select product_name,from_card_no=card_no
,to_card_no=(
select min(card_no) from v_card_no aa
where product_name=a.product_name
and card_no>a.card_no
and not exists(
select * from v_card_no
where product_name=aa.product_name
and card_no=aa.card_no+1))
from v_card_no a
where not exists(
select * from v_card_no
where product_name=a.product_name
and card_no=a.card_no-1)
go

--删除测试
drop table v_card_no

/*--测试结果

product_name         from_card_no         to_card_no           
-------------------- -------------------- -------------------- 
100元充值卡              19906000001          19906000003
100元充值卡              19906000007          19906000009
50元充值卡               19908000002          19908000004
50元充值卡               19908000011          19908000013

(所影响的行数为 4 行)
--*/

#8


这么多啊,谢谢各位,我先试试行不行

#9


还有一个问题就是这个表的数据一般都有几十万上百万数据,还要考虑性能问题,本来在代码里面已经实现了,但是速度太慢,所以放到数据库库端处理

#10


刚才测试了一下,表数据不到12万,用时1分零7秒,这个查询能不能再优化一下,事实上我的问题还不只这么简单,这个视图v_card_no是建立在三个表上,在比较卡号的过程中还要把前面几位去掉,这里只是列出了11位的卡号,还有十八位的卡号,这也是数据库没设计好吧,卡号应该分两个字段存放的,因为比较卡号都是比较后面6位或者7位,要是比较11或者18位的卡号的话,肯定不能直接比较

#11


--建立表格
create table v_card_no(product_name varchar(20),card_no decimal(18,0))
--测试数据
insert v_card_no select '100元充值卡',19906000001
union  all       select '100元充值卡',19906000002
union  all       select '100元充值卡',19906000003
union  all       select '100元充值卡',19906000007
union  all       select '100元充值卡',19906000008
union  all       select '100元充值卡',19906000009
union  all       select '50元充值卡' ,19908000002
union  all       select '50元充值卡' ,19908000003
union  all       select '50元充值卡' ,19908000004
union  all       select '50元充值卡' ,19908000011
union  all       select '50元充值卡' ,19908000012
union  all       select '50元充值卡' ,19908000013
go

--处理
select v_card_no.*,identity(decimal,1,1) as row_id ,inc = '00000000000' 
into #temp 
from v_card_no 

update #temp set inc = convert(varchar(11),card_no) - row_id

select product_name,
min(card_no) as from_card_no,
max(card_no) as to_card_no 
from #temp 
group by product_name,inc

/*结果
product_name    from_card_no    to_card_no
-------------------------------------------------
100元充值卡 19906000001 19906000003
100元充值卡 19906000007 19906000009
50元充值卡 19908000002 19908000004
50元充值卡 19908000011 19908000013
-------------------------------------------------
*/


#12


各位写的Sql代码都很经典,谢谢!用临时表的确要快很多,只花了40多秒

#13


数据量大的话,临时表是最优的

#14


刚开始的思维方式太死了,只想到把数据一条一条取出来处理, chj733(八神苍月) 的这种方法很好,时间主要是花在向临时表插数据上,下次查询只要直接查询临时表就行了;zjcxc(邹建) 的方法技巧性太强了,看了都头晕