求效率高一点的算法 ( 积分: 100 )

  • 主题发起人 主题发起人 狂风123
  • 开始时间 开始时间

狂风123

Unregistered / Unconfirmed
GUEST, unregistred user!
求效率高一点的算法:
某数据集ADODB.Recordset 有多条记录,其中的字段如下:
时间 (dtime), 当前值(value), 坐标名称(location), 坐标x (loc_x), 坐标y (loc_y)
其中 坐标名称(location) 可能重复,但loc_x,loc_y 可以唯一确定location
要求:ADODB.Recordset只能向后单向循环,输出下列表格
时间 坐标名1 坐标名2 坐标名3 坐标名4 ……
12时52分 10(当前值) 0(无当前值) 12 20
12时59分 12 2 0 11
……………………………………
求效率高一点的算法,十分感谢
 
坐标名1 坐标名2 坐标名3 坐标名4 都代表什么?
 
估计是把竖表横向显示吧
 
还没有看懂问题,说详细些!
 
坐标名1 坐标名2 坐标名3 坐标名4 都代表: 字段“坐标名称(location)”里面的值。
也就是 将原本 纵向的数据 横向显示
 
原数据:
dtime value location loc_x loc_y
12时52分 10 武汉 100 120
12时59分 12 襄樊 180 120
15时50分 2 鄂州 220 110
12时59分 15 武汉 100 120
需要转换后 如下显示:
时间 武汉 襄樊 鄂州
12时52分 10 0 0
12时59分 15 12 0
15时50分 0 0 2
要求 直接使用 程序语言来实现(不再使用数据库存储过程)
 
select * from 原数据 group by dtime 的记录集放再一个 List里
for(list)
{
rs = Exe(select value,location from 原数据 where dtime = list.get(i));
Exe(insert rs.get(value),rs.get(location),list.get(i));
}
 
这种数据转置实际上你在建一个临时DATASET,然后循环插入就可以了,实际是在内存中做处理,时间并不是很长的.
 
回復 corpose0
你那个 Exe是什么意思?
 
Exe就是执行select语句并返回一个记录集rs
 
To:corpose0
所有数据 已经在内存了,还有必要再去 SELECT 吗?
 
select * from 原数据 group by dtime 的记录集放再一个 List里
没有把所有的放在内存里,看到了没?我用的是 group by dtime [:)]
 
给你个存储过程 ~~~
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_zj]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_zj]
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
create proc p_zj
@tbname sysname, --要处理的表名
@fdname sysname, --做为转换的列名
@new_fdname sysname= ' ' --为转换后的列指定列名
as
declare @s1 varchar(8000),@s2 varchar(8000)
,@s3 varchar(8000),@s4 varchar(8000),@s5 varchar(8000)
,@i varchar(10)
select @s1= ' ',@s2= ' ',@s3= ' ',@s4= ' ',@s5= ' ',@i= '0 '
select @s1=@s1+ ',@'+@i+ ' varchar(8000) '
,@s2=@s2+ ',@'+@i+ '= '''+case isnull(@new_fdname, ' ') when ' ' then
' '
else
@new_fdname+ '= ' end+ ''''''+name+ ''''''''
-- ,@s2=@s2+ ',@ '+@i+ '= ' '性别= ' ' ' ' '+name+ ' ' ' ' ' ' ' '
,@s3=@s3+ ' select @'+@i+ '=@'+@i+ '+ '',[''+['+@fdname+ ']+ '']= ''''''+cast(['+name+ '] as varchar)+'''''''' from ['+@tbname+ ']'
,@s4=@s4+ ',@'+@i+ '= ''select ''+@'+@i
,@s5=@s5+ '+ '' union all ''+@'+@i
,@i=cast(@i as int)+1
from syscolumns
where object_id(@tbname)=id and name < >@fdname
select @s1=substring(@s1,3,8000)
,@s2=substring(@s2,3,8000)
,@s4=substring(@s4,3,8000)
,@s5=substring(@s5,24,8000)

exec( 'declare '+@s1+ '
select '+@s2+@s3+ '
select '+@s4+ '
exec( '+@s5+ ') ')
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
这个是雏健写的.. .我用了下还不错, 就是需要把数据先存到表里.直接用批处理,不用游标.数度还是很快的,基本上我50个列一下子就转化过来了.
 
帮你顶一个,顺便发个交流群:
无论你是超极菜鸟,亦或是绝顶高手,在这里偶们静下心来平等地交流学习:
delphi交流群:4654765(delphi天堂)欢迎您的加入!让我们共同进步!!
加入者必须改名片为:{地点}+姓名 注:不改者勿扰!
 
我 自己也考虑了 一天 ,写了个 C# 的程序实现,不过循环了2次,而且 根据时间排序了:
//因为日期是排序的,所以可以顺序 写 内容。
Hashtable htable = new Hashtable();
//标题KEY
Hashtable vtable = new Hashtable();
//内容KEY
String strContentHtml = &quot;&quot;;
String curDtime = &quot;&quot;;
rs.MoveFirst();
while (!rs.EOF)
{
//取所有标题
String aKey = rs.Fields[&quot;loc_x&quot;].Value.ToString() + &quot;|&quot;
+ rs.Fields[&quot;loc_y&quot;].Value.ToString();
if (!htable.ContainsKey(aKey))
htable.Add(aKey, rs.Fields[&quot;location&quot;].Value.ToString());
rs.MoveNext();
}
strContentHtml = &quot;<tr><td>时间</td>&quot;;
foreach (String aKey in htable.Keys) //取 标题KEY
{
String value = (String)htable[aKey];
if (value == null) value = &quot;&quot;;
strContentHtml = strContentHtml + &quot;<td>&quot;
+ value + &quot;</td>&quot;;
}
strContentHtml = strContentHtml + &quot;</tr>&quot;;
rs.MoveFirst();
while (!rs.EOF)
{
String aKey = rs.Fields[&quot;loc_x&quot;].Value.ToString() + &quot;|&quot;
+ rs.Fields[&quot;loc_y&quot;].Value.ToString();
String dtime = rs.Fields[&quot;dtime&quot;].Value.ToString();
if (!dtime.Equals(curDtime))
{
if (vtable.Count > 0)
{
foreach (String sKey in htable.Keys) //取 标题KEY
{
if (vtable.ContainsKey(sKey))
{
do
uble value = (Double)vtable[sKey];
strContentHtml = strContentHtml + &quot;<td>&quot;
+ value.ToString() + &quot;</td>&quot;;
}
else

{
strContentHtml = strContentHtml + &quot;<td>0</td>&quot;;
}
}
strContentHtml = strContentHtml + &quot;</tr>&quot;;
}
curDtime = dtime;
strContentHtml = strContentHtml + &quot;<tr><td>&quot;
+ dtime + &quot;</td>&quot;;
vtable.Clear();
vtable.Add(aKey, rs.Fields[&quot;value&quot;].Value);
}
else
{
if (!vtable.ContainsKey(aKey))
vtable.Add(aKey, rs.Fields[&quot;value&quot;].Value);
}

rs.MoveNext();
}
//写最后剩余的
if (vtable.Count > 0)
{
foreach (String aKey in htable.Keys) //取 标题KEY
{
if (vtable.ContainsKey(aKey))
{
do
uble value = (Double)vtable[aKey];
strContentHtml = strContentHtml + &quot;<td>&quot;
+ value.ToString() + &quot;</td>&quot;;
}
else
{
strContentHtml = strContentHtml + &quot;<td>0</td>&quot;;
}
}
strContentHtml = strContentHtml + &quot;</tr>&quot;;
}
return strContentHtml;
 
LZ 的代码是基于网页的。下面也给个存储过程:
create table t(奖惩 varchar(8),次数 int,金额 int,年度 char(4))
insert t
select '大功',2,360,'2002' union all
select '小功',17,1020,'2002' union all
select '小功',3,360,'2002' union all
select '大功',9,1620,'2003' union all
select '嘉獎',2,80,'2003' union all
select '警告',25,-500,'2003' union all
select '警告',1,-40,'2003' union all
select '大功',1,180,'2004' union all
select '嘉獎',12,240,'2004' union all
select '嘉獎',2,80,'2004' union all
select '警告',18,-360,'2004' union all
select '警告',1,-40,'2004' union all
select '大功',3,540,'2005' union all
select '小功',7,420,'2005' union all
select '小過',11,-660,'2005'
go
declare @s varchar(8000)
set @s='select isnull(年度,''合计'') as [年度]'
select @s=@s+',['+奖惩+']=sum(case 奖惩 when '''+奖惩+''' then
金额 else
0 end)'+
',['+奖惩+'次数]=sum(case 奖惩 when '''+奖惩+''' then
1 else
0 end)'
from t group by 奖惩
set @s=@s+',合计=sum(金额) from t group by 年度 with rollup'
exec(@s)
/*
年度 大功 大功次数 嘉獎 嘉獎次数 警告 警告次数 小功 小功次数 小過 小過次数 合计
---- ----------- -------- --------- --------- -------- --------- ------ -------- ---------------------
2002 360 1 0 0 0 0 1380 2 0 0 1740
2003 1620 1 80 1 -540 2 0 0 0 0 1160
2004 180 1 320 2 -400 2 0 0 0 0 100
2005 540 1 0 0 0 0 420 1 -660 1 300
合计 2700 4 400 3 -940 4 1800 3 -660 1 3300
*/
drop table t
 
delphi群:23981160,爱好d的都来
 
看了楼主的代码,已经实现了需求。不过,窃以为除了在纵向上对时间排序之外,如果能
够在横向上对名称排序的话就更好了,呵呵。 [:D]
 
后退
顶部