Microsoft Access 掲示板

IDが連番に並んでいるのか知りたい

24 コメント
views
4 フォロー

access初心者です。テーブルに以下のようなデータがあるとします
ID 数値
19 1.91
20 1.88
21 1.89
22 1.86
この時に数値を昇順に並び替えても、IDが連番に並んでいるか調べたいです。
クエリの昇順だと20と21が逆になっているので、今のままなら21がアウトですよ。と分かるようにしたいです。
お願いいたします

ぽん
作成: 2024/02/08 (木) 12:48:46
通報 ...
1

数値フィールドで昇順に並べ替えたらIDの昇順連番は担保されません。

2
hiroton 2024/02/08 (木) 17:10:57 34d4e@f966d

レコードセット取得して前のレコードと今のレコードの値を比較したらいいんじゃないですかね?

3

「数値を昇順」で「ID」は降順になっていてほしいということですか?

4
ぽん 2024/02/09 (金) 15:50:32 2d148@1925b

並び替え前のテーブルと、並び替えたクエリを数値フィールドで繋ぐってことでしょうか?

5
ぽん 2024/02/09 (金) 15:52:07 2d148@1925b

「数値を昇順」で「ID」は降順 ではなくて、「数値を昇順」で並べたときに、IDが連番になっていれば降順でも昇順でも構わないんです。

6

IDが連番になっていれば降順でも昇順でも構わないんです。

全体が昇順または降順ということですか。
それとも途中から昇順、降順が入れ替わることはありますか。
例えば、最初は昇順だったが、途中から降順に変わるとか。

また、昇順か降順かの判断基準はありますか。

もう少しデータ数の多いサンプルデータを提示してもらえますか。また、降順の場合のサンプルデータと昇順の場合のサンプルデータも提示してもらえますか。

7
りんご 2024/02/09 (金) 17:48:22 935bc@0e907

新しいフィールドを追加して、並び順を登録すればいいんじゃない?
繰返構文、変数値、インクリメント。

8
hatena 2024/02/10 (土) 10:00:48 修正

下記のような仕様だと仮定して。

  • 数値を昇順にした場合、ID全体が昇順または降順で連番になっているかどうかをチェック。
  • 途中から昇順、降順が変わることはない。
  • 必ずIDは連番になっていて抜けがない。
  • 連番になっていないIDはイミディエイトウィンドウに出力。
  • テーブル名は T1
Public Sub SequenceCheck()
    Dim MinId As Long, MaxID As Long
    MinId = DMin("ID", "T1"): MaxID = DMax("ID", "T1")
    
    Dim StepNum As Long, SeqNum As Long
    If DLookup("数値", "T1", "ID=" & MinId) < DLookup("数値", "T1", "ID=" & MaxID) Then
        StepNum = 1   '昇順
        SeqNum = MinId
    Else
        StepNum = -1  '降順
        SeqNum = MaxID
    End If

    
    Dim rs As DAO.Recordset
    Set rs = CurrentDb.OpenRecordset("SELECT * FROM T1 ORDER BY 数値;")
    Do Until rs.EOF
        If rs!ID <> SeqNum Then
            Debug.Print rs!ID
        End If
        SeqNum = SeqNum + StepNum
        rs.MoveNext
    Loop

    rs.Close
    Set rs = Nothing
End Sub
9
ぽん 2024/02/13 (火) 12:39:35 2d148@1925b

数値を昇順にした場合、ID全体が昇順または降順で連番になっているかどうかをチェック。←まさに、やりたいことです!
途中から昇順、降順が変わることはない。←IDは必ず、昇順か降順で飛び番号はありません

連番になっていないIDは、イミディエイトウィンドウに出力。
↑ではなく、テーブルに昇順×とや、降順で×とか表示したいです。できるのならば、フィールドは作成します
お願いいたします

10

テーブルに表示させたいなら、テーブルに表示用のフィールドを追加することになります。

例えば、 連番チェック という名前のテキスト型のフィールドを追加したとして、下記のような感じです。

Public Sub SequenceCheck2()
    Dim MinId As Long, MaxID As Long
    MinId = DMin("ID", "T1"): MaxID = DMax("ID", "T1")
    
    Dim StepNum As Long, SeqNum As Long, stOrder As String
    If DLookup("数値", "T1", "ID=" & MinId) < DLookup("数値", "T1", "ID=" & MaxID) Then
        StepNum = 1   '昇順
        SeqNum = MinId
        stOrder = "昇順"
    Else
        StepNum = -1  '降順
        SeqNum = MaxID
        stOrder = "降順"
    End If

    CurrentDb.Execute "UPDATE T1 SET 連番チェック = Null WHERE Not 連番チェック Is Null;"
    
    Dim rs As DAO.Recordset
    Set rs = CurrentDb.OpenRecordset("SELECT * FROM T1 ORDER BY 数値;")
    Do Until rs.EOF
        If rs!ID <> SeqNum Then
            rs.Edit
            rs!連番チェック = stOrder & "×"
            rs.Update
        End If
        SeqNum = SeqNum + StepNum
        rs.MoveNext
    Loop

    rs.Close
    Set rs = Nothing
End Sub
11
hiroton 2024/02/14 (水) 09:36:22 da393@f966d

フォームに読み込んで表示するとして、フォームの読み込み時イベントに[イベント プロシージャ]を設定して、

Private Sub Form_Load()
    Dim lastRecord As Long
    Dim lastID As Double
    Dim sortSign As Long
        
    lastID = Me!ID
    DoCmd.GoToRecord , , acLast
    lastRecord = Me.CurrentRecord
    sortSign = IIf(lastID < Me!ID, 1, -1)
    
    DoCmd.GoToRecord , Me.Name, acFirst
    lastID = Me!ID - sortSign
    Me!フィールド = Null
    Do
        DoCmd.GoToRecord , Me.Name, acNext
        Me!フィールド = IIf(Me!ID * sortSign > lastID * sortSign, Null, "×")
        lastID = Me!ID
    Loop Until Me.CurrentRecord = lastRecord
End Sub
12
名前なし 2024/02/14 (水) 12:24:44 53dda@1925b

お二人ともありがとうございました。
初心者の私には、即答できないので実際に この構文を加工させていただいて実行してみたいと思います。
ちなみに hatenaさんの場合も、フォームの読み込み時イベントでよろしいですか?

13

テーブルデータを入力または更新したタイミングですね。つまり連番が崩れる可能性のあるタイミングでチェックするということです。

14
hiroton 2024/02/14 (水) 13:12:15 da393@f966d

そういえばこれ、数値を昇順にすると

ID数値上位とチェック下位とチェック
221.8622→20:連番ではない
201.8822→20:連番ではない20→21:連番
211.8920→21:連番21→19:連番ではない
191.9121→19:連番ではない

クエリの昇順だと20と21が逆になっているので、今のままなら21がアウトですよ。と分かるようにしたいです。

全部アウトじゃない?
少なくとも、「21がアウトですよ」はどういう基準でそれがアウトなのか意味が分かりませんね

>> 11のhirotonの回答はその辺適当です

15
ぽん 2024/02/15 (木) 12:45:28 53dda@1925b

ご指摘ありがとうございました。21がアウトですよ の説明です
最大値の22、最小値の19は合っているけれど、数値で並べ替えると22の次が21番が連番じゃなくて
20番になっているからアウトですよ ってことを調べたかったんです。
前回ご指摘をいただいたように4件しか表示していなかったのですみません。 
件数を増やしました。再度ご教授お願い致します。
ID 数値
19 1.91
20 1.90
21 1.89
22 1.86
23  1.88
24  1.81
25  1.81
とデータがあったとき数値を昇順に並び替える
25 1.81
24  1.81
22  1.86
23  1.88
21  1.89
20  1.90
19  1.91
ID 25から24までは連番 21から19番も連番だけど 24から22は連番にならないから「ここからアウト」だよ
ってことを調べたいのです。お願いいたします

17
りんご 2024/02/15 (木) 13:54:16 935bc@0e907 >> 15

「ここからアウト」だよってことを調べたいのです。

 その後、どうしたいの?最終的に、やっている事がレッドカードになる場合、質問不成立です。

18

質問不成立です

すみません。

16

数値が重複する場合があるんですね。
だとすると、前回の私の回答では、うまくいかない場合があるので、ちょっと修正します。

数値が同じ場合、IDの並び順が不定になるので、IDの並び順も指定しておく必要がありました。

Public Sub SequenceCheck3()
    Dim MinId As Long, MaxID As Long
    MinId = DMin("ID", "T1"): MaxID = DMax("ID", "T1")
    
    Dim StepNum As Long, SeqNum As Long, stOrder As String
    If DLookup("数値", "T1", "ID=" & MinId) < DLookup("数値", "T1", "ID=" & MaxID) Then
        StepNum = 1   '昇順
        SeqNum = MinId
        stOrder = "昇順"
    Else
        StepNum = -1  '降順
        SeqNum = MaxID
        stOrder = "降順"
    End If

    CurrentDb.Execute "UPDATE T1 SET 連番チェック = Null WHERE Not 連番チェック Is Null;"
    
    Dim sSQL As String
    sSQL = "SELECT * FROM T1 ORDER BY 数値, ID"
    If stOrder = "降順" Then sSQL = sSQL & " DESC"
    
    Dim rs As DAO.Recordset
    Set rs = CurrentDb.OpenRecordset(sSQL)
    Do Until rs.EOF
        If rs!ID <> SeqNum Then
            rs.Edit
            rs!連番チェック = stOrder & "×"
            rs.Update
        End If
        SeqNum = SeqNum + StepNum
        rs.MoveNext
    Loop

    rs.Close
    Set rs = Nothing
End Sub
19

数値が重複する場合があるんですね。
はい、あります。その場合もあると お伝えしなければいけなかったのですね。すみません。

伝達事項の少ない中で、ご返信本当にありがとうございます。
上記を参考に作成してみます。また壁に当たるかと思いますが、ご指導お願いいたします

20

hatenaさま 参考にさせていただき、今テーブルに入力しているID19から22のチェックができるようになりました。今後チェックするIDが34まで増え、19から22、その途中27から34も一度にチェックしたい時などには、どのように書き換えればよろしいでしょうか?DMin("ID", "T1")やDMax("ID", "T1")を19や34にして複数同じなものを作る以外のスマートの方法をお願いできますか?

21

IDが増えても(レコード件数が増えても)、コードを修正する必要はないです。
全レコードを対象にチェックします。

実際にやってみてうまくいかなかったのでしょうか。
もし、そうなら、どのようなデータでどのような結果になったのか、どこが想定と違うのか説明してください。

22
ぽん 2024/02/19 (月) 12:52:22 53dda@1925b

DMin関数とDmax関数を使用して、テーブルに保存されているIDの最小値から最大値の中でチェックできました。本当にありがとうございます。うまくいかなかったというよりは
最小値や最大値だけでなく、IDが34まで増えたときに19から22の間だけ、27から34の間だけで数値を並び替えて同じようにIDの連番をチェックするときは、どうすればいいんだろうと疑問に思ったからです。
MinId = DMin("ID", "T1"): MaxID = DMax("ID", "T1")の部分を、MinId =19 や MinId =27 MaxID =22 や MaxID=34と書き換えてSub を2つ作れば、私でもできるけど...
同じ処理をするのなら、きっともっと良い方法があるんだろうと邪推しました。お願いできますか?

23
hatena 2024/02/19 (月) 13:49:42 修正

最小値や最大値だけでなく、IDが34まで増えたときに19から22の間だけ、27から34の間だけで数値を並び替えて同じようにIDの連番をチェックするときは、どうすればいいんだろうと疑問に思ったからです。

チェックしたい範囲を引数で渡すようにすればいいでしょう。
ただし、指定した範囲だけチェックしたいのなら、その範囲のレコードを抽出して並び替える必要があります。

同じ処理をするのなら、きっともっと良い方法があるんだろうと邪推しました。お願いできますか?

引数を省略できる設定があります。引数の前に Optional をつけます。

VBA 省略可能な引数 Optional と名前付き引数

引数を省略したは全レコードをチェック、引数が指定してあればその引数間のレコードを対象にするというふうにすればいいでしょう。

上記を考慮すると下記のようなコードになります。

Public Sub SequenceCheck4(Optional MinId As Long = 0, Optional MaxID As Long = 0)
    If MinId = 0 Then MinId = DMin("ID", "T1")
    If MaxID = 0 Then MinId = DMax("ID", "T1")
    
    Dim StepNum As Long, SeqNum As Long, stOrder As String
    If DLookup("数値", "T1", "ID=" & MinId) < DLookup("数値", "T1", "ID=" & MaxID) Then
        StepNum = 1   '昇順
        SeqNum = MinId
        stOrder = "昇順"
    Else
        StepNum = -1  '降順
        SeqNum = MaxID
        stOrder = "降順"
    End If

'    CurrentDb.Execute "UPDATE T1 SET 連番チェック = Null WHERE Not 連番チェック Is Null;"
    
    Dim sSQL As String
    sSQL = "SELECT * FROM T1 Where ID>=" & MinId & " And ID<=" & MaxID & " ORDER BY 数値, ID"
    If stOrder = "降順" Then sSQL = sSQL & " DESC"
    
    Dim rs As DAO.Recordset
    Set rs = CurrentDb.OpenRecordset(sSQL)
    Do Until rs.EOF
        rs.Edit
        If rs!ID <> SeqNum Then
            rs!連番チェック = stOrder & "×"
        Else
            rs!連番チェック = Null
        End If
        rs.Update
        SeqNum = SeqNum + StepNum
        rs.MoveNext
    Loop

    rs.Close
    Set rs = Nothing
End Sub

使用例


'27から34の間だけ連番チェック
Call SequenceCheck4(27, 34)

'全レコードを連番チェック
Call SequenceCheck4()

24
ぽん 2024/02/20 (火) 12:49:13 53dda@1925b

上記の様に変更して、
引数を省略したは全レコードをチェック、引数が指定してあればその引数間のレコードを対象に...
()の中で使い分けができるなんて!!とても助かります。
これで細かいチェックもできます!ありがとうございました