1

平台: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”

表格内容:

行号 fldOne fldTwo fldThree
------------------------------------------------
1 蒲公英 01:00:00 99
2 雏菊 02:15:00 88
3 蒲公英 00:45:00 77
4 蒲公英 00:30:00 10
5 蒲公英 00:15:00 200
6 玫瑰 01:30:00 55
7 雏菊 01:00:00 22
等等 ad nausium

如果我使用:

Select * from tblMain where fldTwo < ’05:00:00’ order by fldOne, fldTwo desc

然后正确返回所有行,按 fldOne 排序,然后按 fldTwo 降序排序(尽管在我展示的示例数据中,所有数据都已按正确顺序排列!)

我想做的是得到每个fldThree的 SUM ,但只能从每个fldOne的第一次出现。

所以,求和我遇到的第一个蒲公英、黛西和玫瑰。例如 99+88+55

目前,我正在以编程方式执行此操作;从上面的 Select 语句返回一个 RecordSet,然后MoveNext遍历每个返回的行,如果我以前从未见过来自fldOne的文本,则仅将fldThree添加到我的“总数”中。它可以工作,但是大多数 Select 查询返回超过 100k 行,所以它很慢(慢是一个相对术语——我的设置大约需要 50 秒)。

实际的 select 语句(从 1.5m 总行中选择大约 100k 行)在一秒钟内完成,这很好。当前的程序循环非常小且紧凑,只是通过 RecordSet 的循环数需要时间。当我打开记录集时,我正在使用 adOpenForwardOnly 和 adLockReadOnly。

这是一个基本上随着更多数据的添加而连续运行的例程,而且fldTwo的“时间”也会有所不同,所以我不能更具体地使用 Select 语句。

到目前为止,我用 SQL 本地完成的所有事情似乎都运行得很快,我希望我可以将逻辑(和工作)从我的程序中拿走,让 SQL 来承受压力。

提前致谢

4

2 回答 2

0

也许这个?

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
于 2012-12-28T16:18:11.703 回答
0

解决这个问题的最好方法是使用窗口函数。这些使您可以枚举组中的行。但是,您需要一些方法来识别第一行。SQL 表本质上是无序的,因此您需要一个列来指定排序。这里有一些想法。

如果你有一个 id 列,它被定义为 anidentity所以它是自动递增的:

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
于 2012-12-28T16:18:47.377 回答