想测试一下你的SQL技术水平吗?相当能考验你能力的面试问题,请有兴趣的朋友进来挑战一下。

forgot2000 2009-06-10 08:14:11
加精
数据库是SQLServer,有一个基本表1如下
描述:英文字段名(中文描述)

PNO(生产单号) PQty(待产量) DayQty(机器日产量) 生产次序
001 100 40 1
002 30 20 2
003 20 10 3

想生成如下的推断计划表2:
Day(第几天) PNO(生产单号) AQty(安排产量)
1 001 40
1 002 0
1 003 0
2 001 40
2 002 0
2 003 0
3 001 20
3 002 10
3 003 0
4 002 20
4 003 0
5 003 10
6 003 10

看懂了吗?我解释一下:凡是到某天还没生产完成的单(包括生产了一部分的或者还没开始生产的),那天的数据都要包括这些单号,生产完成的单则不必显示,如果该单当天按推断不会生产,则AQty(安排产量)为0,请大家看看第3天的数据,该天001单剩下20个没做,机器对001单的日产量是40个,那么机器能够生产完001单之后还剩下半天时间,按照生产次序,001单完成之后是002单,002单要生产30个,机器对002单的日产量是20个,即是说,第3天还有半天时间可以安排生产002单,这半天时间能够生产002单是10个,002单还剩20个,这20个刚好第4天可以生产完,那么第5天就可以开始生产003单

逻辑就是这样,好像并不复杂,但实际操作下来却发现问题远远没有那么简单,有兴趣的朋友,可以自己建立以上的测试表1,如果可以生产计划表2则证明正确,现实正式表的字段和数据远远比测试表大得多,但基本逻辑是一样的,由于海量数据还要考虑效率问题(这个我们可以晚一步去考虑),首要任务是能够生成表2,怎么样?有兴趣挑战一下自己吗?如果能做到的朋友,可以帮忙优化,以尽量少的语句尽量快的实现吗?
...全文
8158 257 打赏 收藏 转发到动态 举报
写回复
用AI写文章
257 条回复
切换为时间正序
请发表友善的回复…
发表回复
fcpslove 2010-04-27
  • 打赏
  • 举报
回复
ooooooooooooooooooooooooooooooooooooooooooo
appleller 2010-04-12
  • 打赏
  • 举报
回复
..............................
fncsxc2010 2010-03-17
  • 打赏
  • 举报
回复
学习!
taozhi_yaoyao 2009-08-17
  • 打赏
  • 举报
回复
没看懂哎
水平太次啊
shenzhenNBA 2009-08-09
  • 打赏
  • 举报
回复
牛,路过学习了...
jc_Lydias 2009-08-08
  • 打赏
  • 举报
回复
.................
tonychen000 2009-08-07
  • 打赏
  • 举报
回复
mark
CrazyRabit 2009-08-07
  • 打赏
  • 举报
回复
declare @leftAty float,@day int,@orderNum int,@PNO varchar(5),@leftDay float,@sumDay float,@partDay float

set @day=1
set @PNO=''
set @orderNum=1
set @partDay=0
while exists(select * from Qty where orderNum=@orderNum)
begin
select top 1 @leftDay=PQty/DayQty,@PNO=PNO from Qty where orderNum=@orderNum
set @sumDay=@leftDay
if(@partDay>0 and @sumDay>@partDay)
insert into Result([Day],PNO,AQty) (select @day,PNO,@partDay*DayQty from Qty where orderNum=@orderNum)
set @sumDay=@sumDay-@partDay
set @leftDay=@sumDay
set @day=@day+1
begin
if(@partDay>0 and @sumDay<@partDay)
begin
set @orderNum=@orderNum+1
set @partDay=@partDay-@sumDay
continue
end


end
while(@leftDay>=1)
begin

insert Result([Day],PNO,AQty) (select @day,PNO,case when (orderNum=@orderNum and @leftDay>=1) then DayQty else 0 end from Qty where orderNum>=@orderNum)
set @leftDay=@leftDay-1
set @day=@day+1
end
if(abs(@leftDay)>0)
begin
insert Result ([Day],PNO,AQty) (select @day,PNO,(@sumDay-Convert(int,@sumDay))*DayQty from Qty where orderNum=@orderNum)
set @partDay= 1-abs(@leftDay)
end
else
set @partDay= 0
set @orderNum=@orderNum+1
end








leoldj 2009-08-06
  • 打赏
  • 举报
回复
搞不懂啊

道行不够啊
talentz 2009-08-06
  • 打赏
  • 举报
回复
现在的计算机编程人员基础太差了,学sql怎么就不知道select 语句后面可以使用group by 吗?弄那么复杂干嘛?精髓的东西都掌握不住,代码的效率能高到哪里去???
zouyx317 2009-08-06
  • 打赏
  • 举报
回复
[Quote=引用 61 楼 yang_ 的回复:]
看看有什么问题

SQL codecreatetable test(
PNOvarchar(5),
PQtyint,
DayQtyint,
生产次序int
)insert testselect'001',100,40 ,1unionallselect'002',30 ,20 ,2unionallselect'003',20 ,10 ,3unionallselect'004',20 ,100 ,4unionallselect'005',20 ,50 ,5unionallselect'006',10 ,100 ,6unionallselect'007',100 ,200 ,7unionallselect'008',20 ,10 ,8go--开始计算select*into #tfrom testcreatetable #r([Day]int,
PNOvarchar(5) ,
AQtyint
)declare@iintdeclare@Aqtyintdeclare@dfloatset@i=1whileexists (select1from #twhere PQty>0)begininsert #rselect@i,PNO,0from #twhere PQty>0orderby 生产次序set@d=1update rset@AQty=casewhen@d<=0then0whenFLOOR(@d*t.DayQty)>=t.PQtythen t.PQtyelseFLOOR(@d*t.DayQty)end
,@d=@d-1.0*@AQty/t.DayQty
,AQty=@AQtyfrom #r r,#t twhere t.PNO=r.PNOand r.[Day]=@iupdate tset
PQty= t.PQty- r.AQtyfrom #t t,#r rwhere t.PNO=r.PNOand r.[Day]=@iset@i=@i+1end--显示结果select*from #rdroptable #rdroptable #t--结果Day


[/Quote]

值得研究,为什么会这样?
ocean07000814 2009-08-06
  • 打赏
  • 举报
回复
学习中
allanic 2009-08-06
  • 打赏
  • 举报
回复
用一条SQL就能解决的事,只不过为了形式上满足lz的结果,需要建个辅助表
CREATE TABLE DAY(DayNum INTEGER);
从1开始插入足够多的天数

然后:
SELECT t3.DayNum,t1.PNO,(CASE WHEN t3.DayNum>t2.FromDay AND t3.DayNum<t2.ToDay+1 THEN (CASE WHEN t2.ToDay<t3.DayNum THEN t2.ToDay ELSE t3.DayNum END)-(CASE WHEN t2.FromDay>t3.DayNum-1 THEN t2.FromDay ELSE t3.DayNum-1 END) ELSE 0 END)*t1.DayQty AQty
FROM TB t1,(
SELECT a.PNO,IFNULL(SUM(b.PQty/b.DayQty),0) FromDay,IFNULL(SUM(b.PQty/b.DayQty),0)+MAX(a.PQty/a.DayQty) ToDay
FROM TB a LEFT JOIN TB b ON b.OrderNum<a.OrderNum
GROUP BY a.PNO
) t2, DAY t3
WHERE t1.PNO=t2.PNO
AND t3.DayNum<t2.ToDay+1
ORDER BY t3.DayNum,t1.PNO


执行结果:
DayNum PNO AQty
---------------------------
1 001 40.00000000
1 002 0.00000000
1 003 0.00000000
2 001 40.00000000
2 002 0.00000000
2 003 0.00000000
3 001 20.00000000
3 002 10.00000000
3 003 0.00000000
4 002 20.00000000
4 003 0.00000000
5 003 10.00000000
6 003 10.00000000
-----------------------------
折shui 2009-08-06
  • 打赏
  • 举报
回复
留下
sadstory 2009-08-06
  • 打赏
  • 举报
回复
我的解答,写在我blog里,http://blog.csdn.net/sadstory/archive/2009/08/06/4418289.aspx
能给看看吗?
zsr_1010 2009-08-04
  • 打赏
  • 举报
回复
好久没写这样的代码了 大家看看我的解决方案吧
首先 为了考虑小单子的情况(一天可以完成多个单子)我多加了几条记录
PNO PQTY DayQTy MakeNum
001 100 40 1
002 30 20 2
003 20 10 3
004 10 100 4 --比原来多的小单子
005 20 100 5 --比原来多的小单子
006 5 100 6 --比原来多的小单子

按照需求来说 一条语句就可以得出所需要的了(虽然格式不一样)
语句为:

select PNO, PQty,DayQty,MakeNum, Cast(PQty*1.0/DayQty as decimal(10,2)) as decDays
,(select Cast(ISNULL(sum(Cast(PQty*1.0/DayQty as decimal(10,2))),0)+1 as int) from T1 where makeNum<c.makeNum) as startDay
,(select ceiling(ISNULL(sum(Cast(PQty*1.0/DayQty as decimal(10,2))),0)) from T1 where makeNum<=c.makeNum) as endDay
from T1 as c
查询出的结果为:
PNO PQTY DayQTy MakeNum needDays startDay endDay

001 100 40 1 2.50 1 3
002 30 20 2 1.50 3 4
003 20 10 3 2.00 5 6
004 10 100 4 0.10 7 7
005 20 100 5 0.20 7 7
006 5 100 6 0.05 7 7
在实际应用中 这样的信息已经可以安排生产了
startDay 表示从第几天开始生成 endDays 表示 生产到第几天为止
为了达到楼主的要求 我构造了一个天数表 T_Days
DayNum (在很多应用中 肯定存在这样一个表 比动态生成 个人认为要好的多了 )
1
2
3
4
5
6
7
8
9
10
11
12
....
好了 查询语句如下:(没有声明一个变量哦)
select DayNum,PNO, PQty,DayQty,MakeNum,
Case when DayNum>=(select Cast(ISNULL(sum(Cast(PQty*1.0/DayQty as decimal(10,2))),0)+1 as int) from T1 where makeNum<c.makeNum)
and DayNum<=(select ceiling(ISNULL(sum(Cast(PQty*1.0/DayQty as decimal(10,2))),0)) from T1 where makeNum<=c.makeNum)
then DayQty else 0 end as aDayQty
from T1 as c
cross join T_Days where DayNum<=(select ceiling(ISNULL(sum(Cast(PQty*1.0/DayQty as decimal(10,2))),0)) from T1
)
and DayNum<=
(select ceiling(ISNULL(sum(Cast(PQty*1.0/DayQty as decimal(10,2))),0)) from T1 where makeNum<=c.makeNum)
order by DayNum,MakeNum ASC

下面是查询结果
DayNum PNO PQTY DayQTy MakeNum aDayQty(当天实际生产量)
1 001 100 40 1 40
1 002 30 20 2 0
1 003 20 10 3 0
1 004 10 100 4 0
1 005 20 100 5 0
1 006 5 100 6 0
2 001 100 40 1 40
2 002 30 20 2 0
2 003 20 10 3 0
2 004 10 100 4 0
2 005 20 100 5 0
2 006 5 100 6 0
3 001 100 40 1 40
3 002 30 20 2 20
3 003 20 10 3 0
3 004 10 100 4 0
3 005 20 100 5 0
3 006 5 100 6 0
4 002 30 20 2 20
4 003 20 10 3 0
4 004 10 100 4 0
4 005 20 100 5 0
4 006 5 100 6 0
5 003 20 10 3 10
5 004 10 100 4 0
5 005 20 100 5 0
5 006 5 100 6 0
6 003 20 10 3 10
6 004 10 100 4 0
6 005 20 100 5 0
6 006 5 100 6 0
7 004 10 100 4 100
7 005 20 100 5 100
7 006 5 100 6 100
好多语句都忘了,花了一个多小时的时间,又重新学习了下 子查询
语句经过测试,希望大家批评指正!









skyctr 2009-08-04
  • 打赏
  • 举报
回复
搬板凳学习!
jjiiaabbiinn 2009-08-03
  • 打赏
  • 举报
回复
路过,但没有时间。。。
jksnt_2000 2009-08-02
  • 打赏
  • 举报
回复
mark
yiyutianmo 2009-08-01
  • 打赏
  • 举报
回复
完全看不懂啊,太菜鸟了
加载更多回复(237)

22,210

社区成员

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

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