Accessでの自動加算方法とは?

このQ&Aのポイント
  • Accessでのデータの自動加算方法について質問があります。
  • 現在の処理をSQLで書き換えたい場合、どのような方法があるのでしょうか?
  • 具体的なコードや手順について教えてください。
回答を見る
  • ベストアンサー

アクセス sqlで自動加算したい

アクセス2010です 現在 Me.Filter = グループ別 Me.FilterOn = True Me.OrderBy = 速い順 Me.OrderByOn = True jj = 1 Me.Recordset.MoveFirst While (Not Me.Recordset.EOF) Me.順番 = jj jj = jj + 1 DoCmd.RunCommand acCmdSaveRecord Me.Recordset.MoveNext Wend これをSQLで jj=0 UPDATE テーブル SET 順番 = Inc(jj) Where ~~ Order ~~~~ なんて書けないですか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.7

> >Set rs = CurrentDB.OpenRecordset(stSQL, dbOpenDynaset) > > やってみましたが、少しは改善されました。 > というのも、この「While~~Wend」間を通るのは3~7回位です。 > しかしこれを53回呼び出しています。 特定のグループ(予約西暦年)だけでなく、テーブル全体を更新したいということでしょうか。 だとしたら、下記のようにすれば OpenRecordset 一回で済みますので高速化できます。 Dim jj As Long Dim atSQL As String Dim rs As DAO.Recordset Dim curDate As Date   stSQL = "SELECT * FROM 予約クエリ OREDER BY 予約西暦年, 計算"   Set rs = CurrentDB.OpenRecordset(stSQL, dbOpenDynaset)   Do Until rs.EOF    If curDate = rs!予約西暦年 Then       jj = jj + 1     Else       jj = 1       curDate = rs!予約西暦年     End If     rs.Edit     rs!順番 = jj     rs.Update     rs.MoveNext   Loop これで改善しないなら、 予約西暦年、計算 フィールドにインデックスを設定する。 計算 フィールドが、クエリ上の演算フィールドなら、その式を見直す。 ぐらいでしょうか。 また、全レコードを更新する必要があるかどうかの検討もしてみてはどうですか。 グループ内の更新したレコード以降だけ順番を振り直せばいいはずです。

situmonnsya
質問者

お礼

おかげさまで、かなり改善されました。 1日の予約欄が3行から7行あります。 例えば日曜は7行あって、その週に定例の予約が複数件発生したとします。 ですので1年分約53週分をLoopさせていますが、時間順に並び替え。 次の年に、定例の予約を更に適用追加。 こんな感じなのですが、 >stSQL = "SELECT * FROM テーブル名 WHERE グループ別 OREDER BY 速い順" >  Set rs = CurrentDB.OpenRecordset(stSQL, dbOpenDynaset) これと、呼び出し先の見直しで体感的に10位早くなりました。 >If curDate = rs!予約西暦年 Then >      jj = jj + 1 >    Else >      jj = 1 >      curDate = rs!予約西暦年 >    End If 処理速度に満足していますので、ご指導のコードはいつかの機会にまた参考させて頂きます。 (バグ混入が怖いので、今回はここまで) いつも的確なご指導、ありがとうございます。

その他の回答 (6)

回答No.6

「DCountが遅い」とよく言われてますが、 DCount自体は遅いというわけではありません。 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1147457126 でも検証されていますが、単純に件数を求めるだけなら、RecordCount とほとんど差はありません。 ただ、順位(連番)を取得するという目的でクエリで使用すると、重くなります。 サプクエリを使うと少しは軽くなりますが、やはり重いです。 自分より前のレコードをカウントするという処理を全レコード分実行することになるので重くなるのです。 テーブル内を繰り返しスキャンすることになりますので。 つまりDCountが遅いのではなく、クエリで順位を取得するには「自分より前のレコードをカウントする」という方法しか無いため重くなるのです。 順位を付ける処理は、SQLより、VBAでレコードセットを開いて先頭から連番を入力していく方法が1スキャンですみますので高速です。 この辺り、結構、誤解があるようですね。 一応、比較するために、SQLで実行する場合のコードも提示しておきますね。 Dim s As String s = "UPDATE 予約クエリ SET 予約クエリ.順番 = " & _ "DCount('*','予約クエリ','計算<= ' & [計算] & ' AND 予約西暦年 = #" & _ Me.予約西暦年 & "#"") " & _ "Where 予約西暦年 = #" & Me.予約西暦年 & "#;" Debug.Print s CurretDB.Execute s イミディエイトウィンドウの出力が、 UPDATE 予約クエリ SET 予約クエリ.順番 = DCount('*','予約クエリ','計算<= ' & [計算] & ' AND 予約西暦年 = #2014/05/18#') Where 予約西暦年 = #2014/05/18#; となるようにします。 現状、提示されている情報から推測したものですので、このままでは動かないかもしれません。

回答No.5

だいぶスレッドが進んでいますが、ちょっと横から失礼します。 SQLでできないかという意図は、 質問で提示のコードでは、フォーム上でレコード移動が発生するし、処理が重いので、 それをなんとかしたいということですよね。 だとしたら、 DoCmd.RunCommand acCmdSaveRecord Me.Recordset.MoveNext でレコード保存、レコード移動しているのが原因です。 下記の方法に書き換えれば、速度は劇的に改善します。 Dim jj As Long Dim rs As DAO.Recordset Me.Filter = グループ別 Me.FilterOn = True Me.OrderBy = 速い順   Me.OrderByOn = True   Set rs = Me.Recordset.Clone   While (Not rs.EOF)     rs.Edit     rs!順番 = jj     rs.Update     rs.MoveNext     jj = jj + 1   Wend   Me.Requery Recordset と Recordset.Clone の違いは下記に詳細に解説していますのでご参照ください。 フォームの Recordset, RecorsetClone, RecordSet.Clone の違いとは? - hatena chips http://hatenachips.blog34.fc2.com/blog-entry-108.html なお、フォームに表示する必要がないのなら、下記の方が高速です。 Dim jj As Long Dim atSQL As String Dim rs As DAO.Recordset   stSQL = "SELECT * FROM テーブル名 WHERE グループ別 OREDER BY 速い順"   Set rs = CurrentDB.OpenRecordset(stSQL, dbOpenDynaset)   While (Not rs.EOF)     rs.Edit     rs!順番 = jj     rs.Update     rs.MoveNext     jj = jj + 1 Wend グループ別 の部分は正しい条件式になるようにしてください。 SQLで、DCountを使うよりも高速なはずです。

situmonnsya
質問者

お礼

>フォーム上でレコード移動が発生するし、処理が重いので、それをなんとかしたいということですよね そのとおりです。 >Set rs = Me.Recordset.Clone 思い出しました。以前使ってみて劇的な速度に感心したことがありました。 >Set rs = CurrentDB.OpenRecordset(stSQL, dbOpenDynaset) やってみましたが、少しは改善されました。 というのも、この「While~~Wend」間を通るのは3~7回位です。 しかしこれを53回呼び出しています。 したがって、呼び出す側の改良が必要ということがわかりました。 もう少し頭を捻ってみます。ありがとうございました。

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.4

(1) >日付<= " & [日付] & "の[日付]には >フォームのフォーカスされているレコードのフィールドの値が入るみたいです。 "UPDATE 予約クエリ SET 予約クエリ.順番 = " + _ "DCount('*','予約クエリ','計算<= " & [計算] & "') " + _ "Where 予約西暦年 = #" + Str(Me.予約西暦年) + "#;" DCount('*','予約クエリ','計算<= " & [計算] & "')          ↓ DCount('*','予約クエリ','計算<= ' & [計算] & ') のように、すべてシングルクォーテーションにしてみてください。 日付<= " & [日付] & " についても、 日付<= ' & [日付] & ' のようにしてみてください。 それから文字列の結合には「+」ではなく「&」を使用 してください。 (2) それから、 "Where 予約西暦年 = #" + Str(Me.予約西暦年) + "#;" では、Str(Me.予約西暦年) のようにStr関数で文字列に 変換しているので「#」で囲みません。 "Where 予約西暦年 = " & Str(Me.予約西暦年) & ";" この場合は Me.予約西暦年 のようにMeキーワードで フォームのコントロールの値を見に行くの「"」で囲んで 文字列の外に出して参照を可能にします。 なお、Str関数で文字列に変換する意図はわかりませんが。

situmonnsya
質問者

お礼

>すべてシングルクォーテーションにしてみて "UPDATE 予約クエリ SET 予約クエリ.順番 = DCount('*','予約クエリ','計算<= ' & [計算] & ') " 試験的に Where 予約西暦年 ははずしてますが、やはり DCount('*','予約クエリ','計算<= ' & [計算] & ') 構文エラーになってしまいました。 「No6」様の方法でやってみようと思います。 また、DCountを誤解してました。 今後安心して使えます。 ありがとうございました。

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.3

(1) まず、 s = "UPDATE 予約クエリ SET 予約クエリ.順番 = DCount('*','予約クエリ','予約西暦年 = #" & [予約西暦年] & "# AND 計算<= " & [計算] & ");" という文字列の、 UPDATE 予約クエリ SET 予約クエリ.順番 = DCount('*','予約クエリ','予約西暦年 = #" & [予約西暦年] & "# AND 計算<= " & [計算] & "); というSQL文でクエリとして登録できるか確認してみてください。 その上で回答のSQL文の書式をよく見てください。 それと、質問では、   UPDATE テーブル SET 順番 = Inc(jj) Where ~~ Order ~~~~ というようにテーブルの更新となっています。条件が違えば 回答の更新クエリが使えない状況もあります。使用条件は 極力正確に質問に織り込んでください。 (2) DCountが遅いと言っても実際に大量レコードで試しても 体感できるほどの差はでません。 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1147457126

situmonnsya
質問者

お礼

AND 計算<= " & [計算] & ");" AND 計算<= " & [計算] & "');" 「)」の前に「'」シングルコーテーションがなかった為でした. ただこれだと全レコードを書き換えにいくので "UPDATE 予約クエリ SET 予約クエリ.順番 = " + _ "DCount('*','予約クエリ','計算<= " & [計算] & "') " + _ "Where 予約西暦年 = #" + Str(Me.予約西暦年) + "#;" としました。 sqlは通るのですが、順番は全て同一の値になり連番になりません。。 日付<= " & [日付] & "の[日付]には フォームのフォーカスされているレコードのフィールドの値が入るみたいです。 もう少し、考えてみます。ありがとうございました。

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.2

No1です。 「速い順」 は日付あるいは時刻としてフィールドは 日付/時刻型としています。そのために   日付 <= #" & [日付] & "# のように、「#」を前後にくっつけています。数値型の 場合だと、   日付<= " & [日付] & " のようになります。

situmonnsya
質問者

補足

ご回答、ありがとうございます。 うまくいきません。 実際には予約システムです。 sqlをかけたいのも、テーブルでなくクエリです。 同年月日内で予約時間の早い順に順番を付けるというものです。(入力された順ということではなく) s = "UPDATE 予約クエリ SET 予約クエリ.順番 = DCount('*','予約クエリ','予約西暦年 = #" & [予約西暦年] & "# AND 計算<= " & [計算] & ");" Debug.Print s DoCmd.RunSQL s 計算=予約時*100+予約分 実行すると Debug.Printで UPDATE 予約クエリ SET 予約クエリ.順番 = DCount('*','予約クエリ','予約西暦年 = #2014/05/18# AND 計算<= 1030); DoCmd.RunSQLで 「 DCount('*','予約クエリ','予約西暦年 = #2014/05/18# AND 計算<= 1020);の文字列の構文エラーです」となります。 どこがまずいのでしょうか? また、Dcountを使わず記述はできないでしょうか? Dcountは処理が遅いと読んだことがあったので。 宜しくお願い致します。

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.1

テーブルのフィールドが分からないので、 こちらで設定します。 たとえば、テーブル名を Tテーブル として、 ID (オートナンバー) 名前 (テキスト型) グループ (数値型) 日付 (日付/時刻型) 順番 (数値型) とします。 ID   名前  グループ   日付     順番 1    田川   3    2014/06/22 2    佐藤   1    2014/03/25 3    中川   2    2014/10/12 4    山田   2    2014/01/31 5    町田   1    2014/09/01 6    相川   3    2014/08/30 7    前田   3    2014/08/02 8    斉藤   1    2014/07/12 のようにテーブルにデータがあるとして、順番というフィールドに グループ別に日付の早い順に連番を振っていくということでいいでしょうか。 UPDATE Tテーブル SET Tテーブル.順番 = DCount("*","Tテーブル","グループ = " & [グループ] & " AND 日付 <= #" & [日付] & "#");

関連するQ&A

  • アクセス2013MoveNextでエラーになります

    Me.Recordset.MoveFirst i = 1 While (Not Me.Recordset.EOF) Me.フィールド = i i = i + 1 Me.Recordset.MoveNext Wend >Me.Recordset.MoveNext ここで、アクセス2010ではエラーになりませんが、アクセス2013でエラーになります。 > i = i + 1 この箇所にブレークポイントを入れて1回1回ストップ、再実行させるとエラーになりません。 なぜでしょう?対処法がありましたらご教授を。

  • ACCESSでfilterとorderbyについて

    ACCESS2000でfilterとorderbyを同時に指定する場合について教えてください。 ACCESS2000とwindows7を使用しております。 あるフォームにテキストボックスとコマンドボタンを用意しております。 テキストに入力した文字を元にfilterをかけております。 Me.filteron=true Me.filter=カラム名 like ~~ filterをした後に特定のカラムでソート(降順)したいと考えております。 上記に記載したfilterの後に Me.OrderByOn = True Me.OrderBy = カラム名 を追加したのですがfilterはするのですが、ソートはしてくれません。 上記以外になにか指定するものがあるのでしょうか。 お手数ですが、お力添えお願い致します。

  • Access フォームから並び替えレポート

    お知恵をお貸しください。 Access2010 フォームでオプショングループを2種類用意しました。 規則グループ 昇順 降順 並び替えグループ ID ふりがな レポートに Private Sub Report_Open(Cancel As Integer) Select Case Forms!フォーム4!fra並べ替え Case 1 Me.OrderBy = "ID ASC" Me.OrderByOn = True Case 2 Me.OrderBy = "ふりがな ASC" Me.OrderByOn = True End Select End Sub 並び替えでは、昇順のみうまくレポートを行えますが。 規則で ID ふりがな を昇順 降順 に行えません。 なにを加えればよいのでしょうか。 よろしくお願いします。

  • Access2007 サブフォームのレコードを一括印刷する方法

    お世話になっております。 サブフォームは帳票型になっており、下記で表示されている全レコードのチェックが入ります。 これと平行して、各レコードを印刷したいのですが、カーソルがあるレコードのみがレコードの数だけ印刷されてしまいます。 これを各レコードごとに印刷したいと思います。 Dim dbs As Database Dim rst As Recordset Dim strSQL As String Set dbs = CurrentDb Set rst = Me.RecordsetClone With rst If .RecordCount > 0 Then .MoveFirst Do Until .EOF .Edit !チェック = True DoCmd.OpenReport "印刷", acNormal, , "コード=" & Me.コード .Update .MoveNext Loop End If .Close End With ご教授いただければ幸いです。よろしくお願いいたします。

  • アクセスVBA 数値の複数抽出について

    アクセスVBAをつかい[厚み]フィールドの0.1と0.5の2つの抽出を 行いたいのですが、0.1のみの抽出は、できるのですが、複数の抽出方法がわからず悩んでいます。 Me.Filter = "[厚み] = 0.1 " Me.FilterOn = True よろしくお願いします。

  • 「Me.Form」と「Me」の違いは?

    アクセスのフォームで並べ替えをする時、 --------------------------------------------------------- Private Sub cmd_昇順_Click() With Me.Form .OrderBy = "フィールド1 ASC" .OrderByOn = True End With End Sub でも Private Sub cmd_昇順_Click() With Me .OrderBy = "フィールド1 ASC" .OrderByOn = True End With End Sub --------------------------------------------------------- でも出来ますが、 「Form」は必要なのでしょうか? あってもなくてもどっちでもいいなら、理由が知りたいです。

  • ACCESSとVBAとレコード

    こんにちわ。 このサイトは何回も利用させて頂いてるのですが、今回も宜しくお願い致します。 環境はOS:Xp・Access2000です。 フォームを開くときにレコードを並べ替えたいのですが、単に「顧客コード」を昇順で並べ替えるには Private Sub Form_Load() Me.OrderBy = "顧客コード" Me.OrderByOn = True End Sub というのは解ったのですが、 何の関連付けもしてない、指定のテーブルの内容を並べ替えるにはどのように記述したらよいのでしょうか? 「Me」の箇所をそのテーブル名 (例えば、顧客テーブル.OrderBy = "顧客コード") のようにすれば良いのでしょうか? 宜しくお願いします。

  • アクセスで3つのフィルターを連携させたい

    3つのコンボックスがあります Combo1 → 都道府県 Combo2 → 市区 Combo3 → 町村 都道府県と市区までは正常にフィルター出来るのですが、町村を選ぶと都道府県や市区も 同じ町村の名前のデータを引っ張ってきてしまいます。 ボタンを付けることも考えましたが、VBAの能力があまりないので、失敗ばかりしています。 良い知恵を教えて頂けないでしょうか。 Private Sub Combo1_AfterUpdate() Dim Strkubun As String Strkubun = Me.Combo1 Me.Filter = "[都道府県]= '" & Strkubun & "'" Me.FilterOn = True Me.Requery End Sub Private Sub Combo2_AfterUpdate() Dim Strkubun As String Strkubun = Me.Combo2 Me.Filter = "[市区]= '" & Strkubun & "'" Me.FilterOn = True Me.Requery End Sub Private Sub Combo3_AfterUpdate() Dim Strkubun As String Strkubun = Me.Combo3 Me.Filter = "[町村]= '" & Strkubun & "'" Me.FilterOn = True Me.Refresh End Sub

  • サブフォームの並べ替えをVBAで指定したい

    親フォームを開くときにサブフォームの並べ替えを実行したいのですが 親フォームのフォームモジュールに Private Sub Form_Load() With Me.Controls("サブフォーム ") .OrderBy = "日時 DESC" .OrderByOn = True End With End Sub としてるのですが、 OrderByの部分で、 実行時エラー438になります。 サブフォーム名は「サブフォーム」です。 サブフォームの中に日時と言うコントロールは存在します。 なぜエラーになるのでしょうか? ちなみにOrderByをなくしても .OrderByOn = True で同じエラーが発生します。

  • accessのレポートの並べ替え条件

    こんにちわ。 いまaccess2000でレポートを作成しています。 そこでレポートの並べ替え条件(昇順/降順)を 呼び出し元であるフォームのある条件によって, 動的に変えたいと思い, レポートファイルのReport_Open()イベントで 下記のようにコーディングしました。 「 Me.OrderByOn = True If [グローバル変数] = "1" Then Me.OrderBy = " [ID] Desc " Else Me.OrderBy = " [ID] " End If 」 ところが実行すると上記の箇所が処理されているにもかかわらず, 並べ替え条件が正しく反映されません。 どうすれば並べ替え条件が正しく反映されるでしょうか? 教えてください。 宜しくお願いします。