平台:SQL Server 2005 Express
免责声明:我是SQL的新手,所以如果你很乐意帮助我解决一个非常简单的问题,那么如果你说话慢一点,用小字,我不会生气的:-)
我有一个表,我想对多行内容求和。但是,我只想对一列中第一次出现的文本进行求和。
Table schema for table 'tblMain'
fldOne {varchar(100)} Example contents: “Dandelion“
fldTwo {varchar(8)} Example contents: “01:00:00” (represents hh:mm:ss)
fldThree {numeric(10,0)} Example contents: “65”
目录:
如果我使用:
Select * from tblMain where fldTwo < ’05:00:00’ order by fldOne, fldTwo desc
然后正确返回所有行,按fldOne和fldTwo降序排序(尽管在我展示的示例数据中,所有数据已经按正确顺序排列!)
我想做的是得到每个fldThree的SUM,但只能从每个fldOne的第一次出现。
所以,SUM我遇到的第一个蒲公英,雏菊和玫瑰。如。99 + 88 + 55
目前,我正在以编程方式进行此操作;从上面的Select语句返回一个RecordSet,并且MoveNext通过每个返回的行,只添加fldThree到我的' total ',如果我从未见过fldOne之前的文本。它可以工作,但是大多数Select查询返回超过100k行,所以它相当慢(慢是一个相对术语-在我的设置中大约需要50秒)。
实际的select语句(从总共150万行中选择大约100k行)在不到一秒的时间内完成,这很好。当前的编程循环非常小且紧凑,只是需要花费时间通过RecordSet的循环次数。当我打开记录集时,我使用adOpenForwardOnly和adLockReadOnly。
这是一个程序,基本上连续运行更多的数据被添加,而且fldTwo '时间'变化,所以我不能更具体的选择语句。
到目前为止,我已经设法用SQL本地做的一切似乎都运行得很快,我希望我能把逻辑(和工作)从我的程序中拿走,让SQL承担压力。
Thanks in advance
最好的方法是使用窗口函数。它们允许您枚举组中的行。但是,您需要某种方法来标识第一行。SQL表本质上是无序的,因此需要一个列来指定排序。以下是一些想法。
如果您有一个id列,它被定义为identity
,因此它是自动递增的:
select sum(fldThree)
from (select m.*,
row_number() over (partition by fldOne order by id) as seqnum
from tblMain m
) m
where seqnum = 1
要获取任意行,可以使用:
select sum(fldThree)
from (select m.*,
row_number() over (partition by fldOne order by (select NULL as noorder)) as seqnum
from tblMain m
) m
where seqnum = 1
或者,如果FldTwo的值顺序相反:
select sum(fldThree)
from (select m.*,
row_number() over (partition by fldOne order by FldTwo desc) as seqnum
from tblMain m
) m
where seqnum = 1
也许是这个?
SELECT SUM(fldThree) as ExpectedSum
FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY fldOne ORDER BY fldTwo DSEC) Rn
FROM tblMain) as A
WHERE Rn = 1