高手请进,这种要求的SELECT语句怎么实现(前面已结贴,继续细化(二)问题每个100分,解答后加贴给分)

时间:2022-05-19 06:47:32
表结构  
表一:计划表  
计划号:字符型  
钢种:字符型  
厚:数值型  
宽度最小值:数值型  
宽度最大值:数值型  
长度最小值:数值型  
长度最大值:数值型  
计划量:数值型 

表二:明细表  
所属计划号:字符型  
钢种:字符型  
厚:数值型  
宽:数值型  
长:数值型  
重量:数值型 


create table #P(c_id char(4),c_gz char(1),c_hd decimal(10),c_kmin decimal(10),c_kmax decimal(10),c_cmin decimal(10),c_cmax decimal(10),c_jhl decimal(10))
create table #d(c_id char(4),c_gz char(1),c_hd decimal(10),c_k decimal(10),c_c decimal(10)),c_zl decimal(10))

insert into #p values('001','A',30,20,20,20,20,100)
insert into #p values('001','A',20,20,40,20,40,100)
insert into #p values('001','A',20,10,60,10,9999,100)
insert into #p values('001','A',20,30,9999,0,9999,100)

insert into #d values('001','A',30,20,20,10)
insert into #d values('001','A',20,30,30,10)
insert into #d values('001','A',20,20,20,10)
insert into #d values('001','A',20,30,60,10)


注意第三条计划其实是完全包含第二条计划的,第四条计划又是部分包含第二、三条计划的。
问题一:能不能选出计划有重叠的所有记录?(自己和自己交叉?)
问题二:能不能统计一下各个计划的完成情况,避免一条明细记录会被统计多次?
问题三:对于重叠的计划,能不能优先将明细的重量统计到范围比较小的计划中?

以上问题每个100分,解答后加贴给分!

22 个解决方案

#1


关注吧。没有发言权。

#2


问题一:
判断两条计划是不是重叠应该很简单,不过写起来麻烦,就用函数代替了:
int IsOver(计划号1,钢种1,厚1,宽度最小值1,宽度最大值1,长度最小值1,长度最大值1,计划号2,钢种2,厚2,宽度最小值2,宽度最大值2,长度最小值2,长度最大值2)
重叠时返回1
SQL如下:
select distinct a.* from #p a, #p b where isover(...) = 1

#3


1:
Select * from #p a join #p b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd 
where a.c_kmin >= b.c_kmin and a.c_kmax <= b.c_kmax
   and a.c_cmin >= b.c_cmin and a.c_cmax <= b.c_cmax

#4


1:
Select * from #p a join #p b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd 
where a.c_kmin >= b.c_kmin and a.c_kmax <= b.c_kmax
   and a.c_cmin >= b.c_cmin and a.c_cmax <= b.c_cmax

#5


2:
Select a.c_id,a.c_gz,a.c_hd,a.c_kmin,a.c_kmax,a.c_cmin,a.c_cmax,   -- 计划号
   sum(case when b.c_k between a.c_kmin and a.c_kmax and b.c_c between a.c_cmin and a.c_cmax then b.c_zl else 0 end) as 完成量
from #p a
join #d b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd
group by a.c_id,a.c_gz,a.c_hd,a.c_kmin,a.c_kmax,a.c_cmin,a.c_cmax

#6


Select * from #d a 
 where not exists(select * from  #d where a.c_id =  c_id and a.c_gz =  c_gz and a.c_hd =  c_hd 
and a.c_k<c_k and a.c_c <c_c )

#7


2:
Select a.c_id,a.c_gz,a.c_hd,a.c_kmin,a.c_kmax,a.c_cmin,a.c_cmax,   -- 计划号
   sum(case when b.c_k between a.c_kmin and a.c_kmax and b.c_c between a.c_cmin and a.c_cmax then b.c_zl else 0 end) as 完成量
from #p a
join #d b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd
group by a.c_id,a.c_gz,a.c_hd,a.c_kmin,a.c_kmax,a.c_cmin,a.c_cmax

#8


txlicenhe(马可&不做技术高手) 的不对
结果出来
001  A    20           20           40           20           40           100
001  A    20           10           60           10           9999         100
就对了

#9


问题2和问题3是不是考虑在
P和D表中各建立一个唯一标识ID来区分会比较容易?
然后建立一个计划与计划的关系表,一个中间的计划与明细关系表(view也是可以的),相信会将问题简化到相当简单的程度,否则,繁杂的语句会让你痛苦到痛苦万分。

#10


txlicenhe(马可&不做技术高手) 的 2 也不对,总共只有4条记录,总量应该是40,可查询结果的完成量已经超过40了,重复统计了很多次了

c_id c_gz c_hd         c_kmin       c_kmax       c_cmin       c_cmax       完成量                                      
---- ---- ------------ ------------ ------------ ------------ ------------ ---------------------------------------- 
001  A    20           10           60           10           9999         30
001  A    20           20           40           20           40           20
001  A    20           30           9999         0            9999         20
001  A    30           20           20           20           20           10

#11


caiyunxia(monkey)的结果,似乎去掉第一条就对了,是不是应该去掉自己和自己比的那条记录?
c_id c_gz c_hd         c_k          c_c          c_zl         
---- ---- ------------ ------------ ------------ ------------ 
001  A    30           20           20           10
001  A    20           30           30           10
001  A    20           30           60           10

#12


对了,如果,如果存在多重重叠,那恐怕是没有单独的语句可以实现了,感觉是只好都做成函数了。。。。。。。

#13


txlicenhe(马可&不做技术高手) 的第二点也有问题
总共只有四条记录,完成总量应该是40,好象重复统计了吧
c_id c_gz c_hd         c_kmin       c_kmax       c_cmin       c_cmax       完成量                                      
---- ---- ------------ ------------ ------------ ------------ ------------ ---------------------------------------- 
001  A    20           10           60           10           9999         30
001  A    20           20           40           20           40           20
001  A    20           30           9999         0            9999         20
001  A    30           20           20           20           20           10

#14


1:
Select a.* from #p a join #p b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd 
where (a.c_kmin > b.c_kmin and a.c_kmax < b.c_kmax
   and a.c_cmin > b.c_cmin and a.c_cmax < b.c_cmax)
or 
(b.c_kmin > a.c_kmin and b.c_kmax < a.c_kmax
   and b.c_cmin > a.c_cmin and b.c_cmax < a.c_cmax)


结果为:
001  A 20 20 40 20 40 100
001  A 20 10 60 10 9999 100

#15


函数就可以避免多重重叠?
现在我的苦恼是数据结构已经定了,而生产系统又不规范,这就是中国程序员的悲哀哦

#16


谢谢txlicenhe(马可&不做技术高手),让我在大数据量中在做一下查询!

#17


关键是函数可以控制循环。
一个while 1>0就可以一直追到底,而不必考虑有多少层。。。。。。。
数据库结构定了?那你的计划/明细表里万一有完全重复的数据(比如录了两遍)——甚至不必完全重叠,例如:存在20-40/30-50两种范围,值为35的数据你准备优先归到哪种情况?
——重复,你是不是该想想怎么处理?
没办法标识记录的话,我看我看后患真的很无穷啊。。。。。。。
如果不会有重复记录(交叉,的范围,包含的范围倒好办),用函数多几个case就可以避免记录的重复使用了。。。。。。。。

#18


比如 
20-40 计划量100
30-50 计划量100
35的数据可以归于任何一个,客户的要求是看最终的所有计划是否完成,或者多生产
其实很多生产部门的生产系统看似混乱,但是肯定有他们存在的合理性,就是苦了我们哦!

如果35的数据有200,我的报表中要先为20-40统计出100,再为30-50统计出100,哎,是不是要死了?

#19


ERP公认的难点: 

1:钢材
2:服饰

#20


要是只有80怎么半?20-40:40/30-50:40?
如果这样,那不是要多一张产量分配表?多一个产量分配录入窗口?
当初是怎么调研的?累死自己了。。。。。。
工作量了不起了!!!
同情楼主。。。。。。

#21


如果是80,随便分也没关系呀,先分给任何一个也合情合理
有很多地方都是既模糊,有合理,就是做不出来

#22


国内TMD谁在好好做ERP!

企业只把它当成软件而不是理念,
软件公司把当成功能而不是思想;
两边都巴不得3天就完成“上ERP”的光荣使命,不晕才怪!
做到天亮,累到天光!

——感想而已,不过可能是眼界小的缘故,感觉国内做ERP真的很成功的企业倒真的没有,个人觉得企业还不如务实一点。

#1


关注吧。没有发言权。

#2


问题一:
判断两条计划是不是重叠应该很简单,不过写起来麻烦,就用函数代替了:
int IsOver(计划号1,钢种1,厚1,宽度最小值1,宽度最大值1,长度最小值1,长度最大值1,计划号2,钢种2,厚2,宽度最小值2,宽度最大值2,长度最小值2,长度最大值2)
重叠时返回1
SQL如下:
select distinct a.* from #p a, #p b where isover(...) = 1

#3


1:
Select * from #p a join #p b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd 
where a.c_kmin >= b.c_kmin and a.c_kmax <= b.c_kmax
   and a.c_cmin >= b.c_cmin and a.c_cmax <= b.c_cmax

#4


1:
Select * from #p a join #p b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd 
where a.c_kmin >= b.c_kmin and a.c_kmax <= b.c_kmax
   and a.c_cmin >= b.c_cmin and a.c_cmax <= b.c_cmax

#5


2:
Select a.c_id,a.c_gz,a.c_hd,a.c_kmin,a.c_kmax,a.c_cmin,a.c_cmax,   -- 计划号
   sum(case when b.c_k between a.c_kmin and a.c_kmax and b.c_c between a.c_cmin and a.c_cmax then b.c_zl else 0 end) as 完成量
from #p a
join #d b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd
group by a.c_id,a.c_gz,a.c_hd,a.c_kmin,a.c_kmax,a.c_cmin,a.c_cmax

#6


Select * from #d a 
 where not exists(select * from  #d where a.c_id =  c_id and a.c_gz =  c_gz and a.c_hd =  c_hd 
and a.c_k<c_k and a.c_c <c_c )

#7


2:
Select a.c_id,a.c_gz,a.c_hd,a.c_kmin,a.c_kmax,a.c_cmin,a.c_cmax,   -- 计划号
   sum(case when b.c_k between a.c_kmin and a.c_kmax and b.c_c between a.c_cmin and a.c_cmax then b.c_zl else 0 end) as 完成量
from #p a
join #d b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd
group by a.c_id,a.c_gz,a.c_hd,a.c_kmin,a.c_kmax,a.c_cmin,a.c_cmax

#8


txlicenhe(马可&不做技术高手) 的不对
结果出来
001  A    20           20           40           20           40           100
001  A    20           10           60           10           9999         100
就对了

#9


问题2和问题3是不是考虑在
P和D表中各建立一个唯一标识ID来区分会比较容易?
然后建立一个计划与计划的关系表,一个中间的计划与明细关系表(view也是可以的),相信会将问题简化到相当简单的程度,否则,繁杂的语句会让你痛苦到痛苦万分。

#10


txlicenhe(马可&不做技术高手) 的 2 也不对,总共只有4条记录,总量应该是40,可查询结果的完成量已经超过40了,重复统计了很多次了

c_id c_gz c_hd         c_kmin       c_kmax       c_cmin       c_cmax       完成量                                      
---- ---- ------------ ------------ ------------ ------------ ------------ ---------------------------------------- 
001  A    20           10           60           10           9999         30
001  A    20           20           40           20           40           20
001  A    20           30           9999         0            9999         20
001  A    30           20           20           20           20           10

#11


caiyunxia(monkey)的结果,似乎去掉第一条就对了,是不是应该去掉自己和自己比的那条记录?
c_id c_gz c_hd         c_k          c_c          c_zl         
---- ---- ------------ ------------ ------------ ------------ 
001  A    30           20           20           10
001  A    20           30           30           10
001  A    20           30           60           10

#12


对了,如果,如果存在多重重叠,那恐怕是没有单独的语句可以实现了,感觉是只好都做成函数了。。。。。。。

#13


txlicenhe(马可&不做技术高手) 的第二点也有问题
总共只有四条记录,完成总量应该是40,好象重复统计了吧
c_id c_gz c_hd         c_kmin       c_kmax       c_cmin       c_cmax       完成量                                      
---- ---- ------------ ------------ ------------ ------------ ------------ ---------------------------------------- 
001  A    20           10           60           10           9999         30
001  A    20           20           40           20           40           20
001  A    20           30           9999         0            9999         20
001  A    30           20           20           20           20           10

#14


1:
Select a.* from #p a join #p b on a.c_id = b.c_id and a.c_gz = b.c_gz and a.c_hd = b.c_hd 
where (a.c_kmin > b.c_kmin and a.c_kmax < b.c_kmax
   and a.c_cmin > b.c_cmin and a.c_cmax < b.c_cmax)
or 
(b.c_kmin > a.c_kmin and b.c_kmax < a.c_kmax
   and b.c_cmin > a.c_cmin and b.c_cmax < a.c_cmax)


结果为:
001  A 20 20 40 20 40 100
001  A 20 10 60 10 9999 100

#15


函数就可以避免多重重叠?
现在我的苦恼是数据结构已经定了,而生产系统又不规范,这就是中国程序员的悲哀哦

#16


谢谢txlicenhe(马可&不做技术高手),让我在大数据量中在做一下查询!

#17


关键是函数可以控制循环。
一个while 1>0就可以一直追到底,而不必考虑有多少层。。。。。。。
数据库结构定了?那你的计划/明细表里万一有完全重复的数据(比如录了两遍)——甚至不必完全重叠,例如:存在20-40/30-50两种范围,值为35的数据你准备优先归到哪种情况?
——重复,你是不是该想想怎么处理?
没办法标识记录的话,我看我看后患真的很无穷啊。。。。。。。
如果不会有重复记录(交叉,的范围,包含的范围倒好办),用函数多几个case就可以避免记录的重复使用了。。。。。。。。

#18


比如 
20-40 计划量100
30-50 计划量100
35的数据可以归于任何一个,客户的要求是看最终的所有计划是否完成,或者多生产
其实很多生产部门的生产系统看似混乱,但是肯定有他们存在的合理性,就是苦了我们哦!

如果35的数据有200,我的报表中要先为20-40统计出100,再为30-50统计出100,哎,是不是要死了?

#19


ERP公认的难点: 

1:钢材
2:服饰

#20


要是只有80怎么半?20-40:40/30-50:40?
如果这样,那不是要多一张产量分配表?多一个产量分配录入窗口?
当初是怎么调研的?累死自己了。。。。。。
工作量了不起了!!!
同情楼主。。。。。。

#21


如果是80,随便分也没关系呀,先分给任何一个也合情合理
有很多地方都是既模糊,有合理,就是做不出来

#22


国内TMD谁在好好做ERP!

企业只把它当成软件而不是理念,
软件公司把当成功能而不是思想;
两边都巴不得3天就完成“上ERP”的光荣使命,不晕才怪!
做到天亮,累到天光!

——感想而已,不过可能是眼界小的缘故,感觉国内做ERP真的很成功的企业倒真的没有,个人觉得企业还不如务实一点。