1

プラットフォーム:SQL Server 2005 Express

免責事項:私はSQLの初心者なので、非常に簡単な質問を喜んで手伝ってくれるなら、ゆっくり話して小さな言葉を使っても気分を害することはありません:-)

複数の行の内容を合計したいテーブルがあります。ただし、別の列に最初に出現するテキストについてのみ、1つの列を合計したいと思います。

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”

表の内容:

行番号fldOnefldTwofldThree
------------------------------------------------
1タンポポ01:00:0099
2デイジー02:15:0088
3タンポポ00:45:0077
4タンポポ00:00:0010
5タンポポ00:15:00200
6ローズ01:30:0055
7デイジー01:00:0022
など広告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クエリは100,000行を超えるため、非常に低速です(相対的な用語であるため、セットアップに約50秒かかります)。

実際のselectステートメント(合計150万行から約10万行を選択)は、1秒以内に完了します。これは問題ありません。現在のプログラムループは非常に小さく、タイトです。時間がかかるのは、RecordSetを通過するループの数だけです。レコードセットを開くときに、adOpenForwardOnlyとadLockReadOnlyを使用しています。

This is a routine that basically runs continuously as more data is added, and also the fldTwo 'times' vary, so I can't be more specific with the Select statement.

Everything that I’ve so far managed to do natively with SQL seems to run quickly and I’m hoping I can take the logic (and work) away from my program and get SQL to take the strain.

Thanks in advance

4

2 に答える 2

0

これにアプローチする最良の方法は、ウィンドウ関数を使用することです。これらを使用すると、グループ内の行を列挙できます。ただし、最初の行を識別する何らかの方法が必要です。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
于 2012-12-28T16:18:47.377 に答える
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 に答える