--示例表:
create table music(id int identity(1,1),length int)
insert music select 200
union all select 249
union all select 58
union all select 109
union all select 344
union all select 294
union all select 43
union all select 296
union all select 87
union all select 102
union all select 336
union all select 158
union all select 265
union all select 332
union all select 132
union all select 252
union all select 275
union all select 243
union all select 228
union all select 205
union all select 324
union all select 164
union all select 30
union all select 268
union all select 105
union all select 84
union all select 34
union all select 285
union all select 73
union all select 159
union all select 154
union all select 77
union all select 261
union all select 71
union all select 101
union all select 94
union all select 133
union all select 251
union all select 80
union all select 296
union all select 314
union all select 338
union all select 25
union all select 330
union all select 218
union all select 198
union all select 300
union all select 307
union all select 123
union all select 342
union all select 33
union all select 106
union all select 261
union all select 137
union all select 281
union all select 309
union all select 278
union all select 336
union all select 319
union all select 212
union all select 353
union all select 323
union all select 8
union all select 42
union all select 226
union all select 168
union all select 61
union all select 325
union all select 318
union all select 155
union all select 103
union all select 77
union all select 39
union all select 297
union all select 181
union all select 196
union all select 256
union all select 196
union all select 166
union all select 182
union all select 165
union all select 151
union all select 244
union all select 79
union all select 252
union all select 315
union all select 286
union all select 205
union all select 331
union all select 220
union all select 249
union all select 248
union all select 342
union all select 42
union all select 82
union all select 244
union all select 224
union all select 193
union all select 166
union all select 141
union all select 230
union all select 296
union all select 123
union all select 177
union all select 100
union all select 114
union all select 216
union all select 229
union all select 220
union all select 108
union all select 179
union all select 229
union all select 134
union all select 274
union all select 164
union all select 335
union all select 59
union all select 206
union all select 274
union all select 287
union all select 181
union all select 257
union all select 318
union all select 341
union all select 59
union all select 360
union all select 309
union all select 158
union all select 52
union all select 264
union all select 83
union all select 352
union all select 311
union all select 46
union all select 84
union all select 271
union all select 252
union all select 102
union all select 337
union all select 285
union all select 342
union all select 238
union all select 273
union all select 206
union all select 92
union all select 272
union all select 169
union all select 333
union all select 89
union all select 22
union all select 98
union all select 35
union all select 38
union all select 9
union all select 350
union all select 128
union all select 303
union all select 150
union all select 339
union all select 342
union all select 109
union all select 34
union all select 125
union all select 22
union all select 176
union all select 172
union all select 96
union all select 259
union all select 35
create table music(id int identity(1,1),length int)
insert music select 200
union all select 249
union all select 58
union all select 109
union all select 344
union all select 294
union all select 43
union all select 296
union all select 87
union all select 102
union all select 336
union all select 158
union all select 265
union all select 332
union all select 132
union all select 252
union all select 275
union all select 243
union all select 228
union all select 205
union all select 324
union all select 164
union all select 30
union all select 268
union all select 105
union all select 84
union all select 34
union all select 285
union all select 73
union all select 159
union all select 154
union all select 77
union all select 261
union all select 71
union all select 101
union all select 94
union all select 133
union all select 251
union all select 80
union all select 296
union all select 314
union all select 338
union all select 25
union all select 330
union all select 218
union all select 198
union all select 300
union all select 307
union all select 123
union all select 342
union all select 33
union all select 106
union all select 261
union all select 137
union all select 281
union all select 309
union all select 278
union all select 336
union all select 319
union all select 212
union all select 353
union all select 323
union all select 8
union all select 42
union all select 226
union all select 168
union all select 61
union all select 325
union all select 318
union all select 155
union all select 103
union all select 77
union all select 39
union all select 297
union all select 181
union all select 196
union all select 256
union all select 196
union all select 166
union all select 182
union all select 165
union all select 151
union all select 244
union all select 79
union all select 252
union all select 315
union all select 286
union all select 205
union all select 331
union all select 220
union all select 249
union all select 248
union all select 342
union all select 42
union all select 82
union all select 244
union all select 224
union all select 193
union all select 166
union all select 141
union all select 230
union all select 296
union all select 123
union all select 177
union all select 100
union all select 114
union all select 216
union all select 229
union all select 220
union all select 108
union all select 179
union all select 229
union all select 134
union all select 274
union all select 164
union all select 335
union all select 59
union all select 206
union all select 274
union all select 287
union all select 181
union all select 257
union all select 318
union all select 341
union all select 59
union all select 360
union all select 309
union all select 158
union all select 52
union all select 264
union all select 83
union all select 352
union all select 311
union all select 46
union all select 84
union all select 271
union all select 252
union all select 102
union all select 337
union all select 285
union all select 342
union all select 238
union all select 273
union all select 206
union all select 92
union all select 272
union all select 169
union all select 333
union all select 89
union all select 22
union all select 98
union all select 35
union all select 38
union all select 9
union all select 350
union all select 128
union all select 303
union all select 150
union all select 339
union all select 342
union all select 109
union all select 34
union all select 125
union all select 22
union all select 176
union all select 172
union all select 96
union all select 259
union all select 35
表music有length上的聚集索引
穷举, 没有速度可言.
如果没有这种组合,不列出也可以,只列出有的即可。
多谢!!
能写个速度较快的例子吗?
多谢
这个是算法问题……要速度的话,建议还是不要找最优解了,“贪心”一点,随机取id,累加到接近一小时就好了,速度才有保证----------------------------------------------------------
问题是,他限定的个数N
DECLARE @beginid int, @endid int
SELECT
@beginid = 5,
@endid = 360-- 生成随机数据SELECT TOP 20000
id=IDENTITY(int,1,1),
length = (ABS(CHECKSUM(NEWID())) % (@endid - @beginid + 1)) + @beginid
INTO tb
FROM sysobjects a,sysobjects b,sysobjects cgo
--存储过程
Create proc p_test
@N int
as--随机产生数据
declare @t table(id int IDENTITY(1,1),tid int,length int)
set rowcount @N
insert @t(tid,length)
select id,length from tb order by newid()set rowcount 0--先调整到<=3600
declare @tid int
declare @id intwhile (select sum(length) from @t)>3600
begin
select top 1 @tid=tid from @t order by length desc
update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=(select top 1 id from tb
where length<t.length
and id not in (select tid from @t)
order by newid()
)
end--开始调大
while (select sum(length) from @t)<3600 and exists (
select 1 from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
)
begin
select top 1 @tid=t.tid,@id=b.id
from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
order by 3600-(select sum(length) from @t)-(b.length-t.length) update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=@id
end--显示数据
select * from @tselect sum(length) as sLength from @tgo
--调用
exec p_test 20
alter proc p_test
@N int
as--随机产生数据
declare @t table(id int IDENTITY(1,1),tid int,length int)
set rowcount @N
insert @t(tid,length)
select id,length from tb order by newid()set rowcount 0--先调整到<=3600
declare @tid int
declare @id intwhile (select sum(length) from @t)>3600
begin
select top 1 @tid=tid from @t order by length desc
update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=(select top 1 id from tb
where length<t.length
and id not in (select tid from @t)
order by newid()
)
end--开始调大
while (select sum(length) from @t)<3600 and exists (
select 1 from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
and b.id not in (select tid from @t)
)
begin
select top 1 @tid=t.tid,@id=b.id
from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
and b.id not in (select tid from @t)
order by 3600-(select sum(length) from @t)-(b.length-t.length) update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=@id
end--显示数据
select * from @tselect sum(length) as sLength from @tgo
贴个运行结果(我的破电脑用时3分49秒)--调用
exec p_test 120
go
--结果
id tid length
----------- ----------- -----------
1 329 15
2 14800 42
3 5039 28
4 11179 32
5 1621 49
6 4204 9
7 12793 10
8 6304 48
9 4292 16
10 3572 29
11 18805 30
12 9251 20
13 4937 5
14 5536 35
15 18171 16
16 9668 39
17 15467 9
18 7838 17
19 16049 19
20 19330 23
21 14697 30
22 6714 39
23 18786 27
24 12052 47
25 16922 42
26 5740 38
27 6962 18
28 12816 25
29 18983 6
30 5856 21
31 17324 51
32 9864 40
33 8024 32
34 7051 42
35 13226 8
36 17147 9
37 3483 36
38 5210 25
39 7843 26
40 10411 52
41 19844 46
42 17172 29
43 19447 8
44 14357 51
45 1730 17
46 4420 25
47 16655 31
48 14869 54
49 8476 9
50 1675 42
51 18817 45
52 6929 45
53 15266 55
54 3117 28
55 3545 51
56 17955 50
57 4688 18
58 796 54
59 12802 52
60 15721 32
61 2945 48
62 4063 26
63 11223 23
64 1452 18
65 14162 30
66 13035 38
67 1663 43
68 8202 18
69 15757 23
70 14314 16
71 7181 30
72 10930 46
73 15378 37
74 3021 53
75 16651 53
76 4360 20
77 19383 46
78 15318 37
79 5191 23
80 2796 29
81 12015 54
82 2570 18
83 15681 37
84 2714 38
85 12667 26
86 7498 15
87 19881 54
88 16191 11
89 11124 20
90 19672 15
91 17662 10
92 8737 41
93 7094 33
94 14647 6
95 5067 6
96 5142 13
97 7070 6
98 18621 16
99 13044 9
100 10769 39
101 2364 31
102 401 32
103 2588 51
104 17051 17
105 15797 49
106 2337 39
107 7992 18
108 14961 13
109 4972 8
110 16969 50
111 11314 43
112 14258 23
113 3181 40
114 13381 34
115 8319 10
116 10846 30
117 18992 51
118 1550 12
119 3076 51
120 16876 27(所影响的行数为 120 行)sLength
-----------
3600(所影响的行数为 1 行)
除了速度不是很理想外,另外还有时候找不到这种组合,即正好=3600的N个组合不存在,
实际上是存在的。
这个不知该如何处理??
谢谢!!
ALTER proc p_test
@N int
as--随机产生数据
declare @t table(id int IDENTITY(1,1),tid int,length int)
set rowcount @N
insert @t(tid,length)
select id,length from tb order by newid()set rowcount 0--先调整到<=3600
declare @tid int
declare @id intwhile (select sum(length) from @t)>3600
begin
select top 1 @tid=tid from @t order by length desc
update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=(select top 1 id from tb
where length<t.length
and id not in (select tid from @t)
order by newid()
)
end--开始调大
while (select sum(length) from @t)<3600 and exists (
select 1 from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
and b.length>t.length
and b.id not in (select tid from @t)
)
begin
select top 1 @tid=t.tid,@id=b.id
from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
and b.length>t.length
and b.id not in (select tid from @t)
order by 3600-(select sum(length) from @t)-(b.length-t.length) update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=@id
end--显示数据
select * from @tselect sum(length) as sLength from @t
GO
谢谢!!
这样还会找不到N个组合起来,其和=3600
实际上存在。麻烦再看看
能求相近可大于小于或等于,不能求最按近, 否则只能穷举
---------------------------------------------------------------也可以,关键是得有个差不多的结果。速度当然也很重要。有什么好办法吗?谢了!!
找不到N个组合起来,其和=3600
实际上存在。的情况
ALTER proc p_test
@N int
as--随机产生数据
declare @t table(id int IDENTITY(1,1),tid int,length int)
set rowcount @N
insert @t(tid,length)
select id,length from tb order by newid()set rowcount 0--先调整到<=3600
declare @tid int
declare @id intwhile (select sum(length) from @t)>3600
begin
select top 1 @tid=tid from @t order by length desc
update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=(select top 1 id from tb
where length<t.length
and id not in (select tid from @t)
order by newid()
)
end--开始调大
while (select sum(length) from @t)<3600 and exists (
select 1 from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
and b.length>t.length
and b.id not in (select tid from @t)
)
begin
select top 1 @tid=t.tid,@id=b.id
from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
and b.length>t.length
and b.id not in (select tid from @t)
order by case when 3600-(select sum(length) from @t)-(b.length-t.length)=0 then 0 else 1 end,newid()
update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=@id
end--显示数据
select * from @tselect sum(length) as sLength from @t
GO
N=11 总和只有3600,用时<1秒
N=12 总和只有3600,用时<1秒
N=20 总和只有3600,用时<1秒
N=40 总和只有3600,用时<1秒
N=50 总和只有3600,用时<1秒
N=51 总和只有3600,用时<1秒
N=52 由于最小的52条总和3702,死循环
帮帮忙,写个存储过程吧
多谢了
我再试试看
ALTER proc p_test
@N int
as--随机产生数据
declare @t table(id int IDENTITY(1,1),tid int,length int)
set rowcount @N
insert @t(tid,length)
select id,length from tb order by newid()set rowcount 0--先调整到<=3600
declare @tid int
declare @id intwhile (select sum(length) from @t)>3600 and exists (
select 1 from @t t,tb b
where t.length>b.length
and b.id not in (select tid from @t)
)
begin
select top 1 @tid=tid from @t order by length desc
update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=(select top 1 id from tb
where length<t.length
and id not in (select tid from @t)
order by newid()
)
end--开始调大
while (select sum(length) from @t)<3600 and exists (
select 1 from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
and b.length>t.length
and b.id not in (select tid from @t)
)
begin
select top 1 @tid=t.tid,@id=b.id
from @t t,tb b
where t.tid<>b.id
and 3600-(select sum(length) from @t)-(b.length-t.length)>=0
and b.length>t.length
and b.id not in (select tid from @t)
order by case when 3600-(select sum(length) from @t)-(b.length-t.length)=0 then 0 else 1 end,newid()
update t
set tid=b.id,length=b.length
from @t t,tb b
where t.tid=@tid
and b.id=@id
end--显示数据
select * from @tselect sum(length) as sLength from @t
GO
p_test 100 耗时2分15秒
p_test 120 耗时3分51秒
究竟哪个效率更高些啊?
http://blog.csdn.net/zjcxc/archive/2004/08/06/67518.aspx但记录量一大,根本运行不了,时间超长。哪位能改一下呢?
其实我只要得到一个组合就可以了。没必要找出所有组合。谢谢!!
AS BEGIN --DECLARE @n int --歌曲个数
DECLARE @t TABLE (id int,length int ,uid int IDENTITY(1,1),diff int)
DECLARE @AVG int
DECLARE @CurTotal int --当前计算的结果
DECLARE @Times int --循环次数
DECLARE @Result TABLE (length int ,ids varchar(800))
DECLARE @IDS varchar(800)
--初始化
--SET @n = 10
SET @AVG = 0
SET @CurTotal = 0
SET @Times = 0
SET @IDS = ''SELECT @AVG = 3600 /@n INSERT INTO @t(id,length) SELECT TOP 120 ID,LENGTH FROM music order by abs(@AVG - length)
DELETE FROM @t WHERE uid > @n
SELECT @CurTotal = SUM(LENGTH) FROM @t
SELECT @IDS = @IDS +CAST(ID AS varchar(6)) +',' FROM @t
INSERT INTO @Result SELECT @CurTotal,@IDS
WHILE @Times < 10 AND ABS(@CurTotal - 3600)>0BEGIN--计算替换掉每个长度后与总数的差
UPDATE @t SET diff = BB.diff FROM @t AS AA INNER JOIN (
SELECT B.UID,3600- (select SUM(length) from @t as AA where AA.uid !=B.uid) as diff FROM @t AS B
) AS BB ON AA.UID = BB.UId ----从现在库中找到一个与差值最近的记录替换掉
Update @t SET id = BB.ID,length = BB.length FROM @t AS AA INNER JOIN (
select TOP 1 A.UID,B.ID,b.length from @t AS A inner join music AS b ON A.ID != B.ID ORDER BY ABS(A.diff-b.length)) AS BB ON AA.uid = BB.uID
SELECT @CurTotal = SUM(LENGTH) FROM @t
SELECT @IDS = ''
SELECT @IDS = @IDS +CAST(ID AS varchar(6)) +',' FROM @t
INSERT INTO @Result SELECT @CurTotal,@IDS
SET @Times = @Times +1END SELECT @IDS = AA.ids from (select top 1 ids FROM @Result order by abs(length-3600)
) AS AASELECT @CurTotal
SELECT @IDS
--RETURN @idsEND
测试了一下,你的速度好快。原理正在看。继续测试,看原理。首先表示感谢