Microsoft Access 掲示板

単純なキーブレイク処理 / 2

9 コメント
views
2

select * from Mtbl_社員 ORDER BY No

No は Access SQL における予約語の 1 つであり、
Yes/No 型( VBA における Boolean 型)の False 値、
数値型の 0 と同義です。

(最初からそんな名前はつけない方がよいですが)
フィールド名として識別させたいのであれば、[]で囲ってください。

select * from Mtbl_社員 ORDER BY [No]

対称対象はテーブルで、Noはレコードの識別子です。

テーブル[Mtbl_社員]の主キーはフィールド[No]である、
という意味だとして、

Noが連続しない場合(固有のレコード)、は削除したいです。

107 1
107 2
107 3
110 1・・・削除
111 1・・・削除
123 1
123 2

これはどのテーブルのレコードのことをおっしゃっているのでしょうか。

[No]が主キーであれば、[No]の値が他のレコードと重複するレコードを
テーブル[Mtbl_社員]に格納することは出来ないはずですが。

通報 ...
  • 3
    はづき 2025/05/09 (金) 18:06:28 69f3e@da8eb >> 2

    実際のコードとは違いまして、簡略化したコードを載せています。
    ご指摘の通り、Noは使っていません。

    Noは社員コードの意でして、主キーではありません。
    Mtbl_社員(現所属)の社員コードとご理解ください。
    簡易チェックのためのテンポラリーの抽出で、所属が専任ではなく、兼任の人を抽出したいという意図があります。

    一応、このコードでも削除自体はできていまして、
    ただ、あまりいいやり方ではないのかなという懸念と、
    最終レコードの社員が1レコードのみの場合の削除ができていないという詰めが甘いです。

    ループを回す前に、Movelastをして、最終レコードの社員が1レコードの場合は削除、
    MoveFirstとするようなお粗末なやり方を考えました。

    4

    Noは社員コードの意でして、主キーではありません。

    では、以下[社員コード]と読み替えます。

    所属が専任ではなく、兼任の人を抽出したい

    単純に「[Mtbl_社員]に格納されているレコードのうち、
    [社員コード]の値が同一であるレコード同士を 1 つのグループとみなし、かつ
    『レコード件数が 2 件以上であるグループ』に含まれるレコードを抽出したい」
    ということでしょうか。

    SELECT [Mtbl_社員].* 
    FROM [Mtbl_社員] 
    INNER JOIN 
        (SELECT tmp.[社員コード] 
         FROM [Mtbl_社員] AS tmp 
         GROUP BY tmp.[社員コード] 
         HAVING Count(*) > 1) AS [兼任社員抽出クエリ] 
    ON [Mtbl_社員].[社員コード] = [兼任社員抽出クエリ].[社員コード]
    ORDER BY [Mtbl_社員].[社員コード];
    

    例えば、以上のような選択クエリを作成なされば同様の結果が得られるはずです。

    簡易チェックのためのテンポラリーの抽出

    抽出されたレコードに対し、更に何らかの編集操作を行いたい場合は、
    上記の選択クエリの結果を同一構造の一時テーブルに出力するように
    なさればよいでしょう。

    5
    はづき 2025/05/09 (金) 18:58:27 69f3e@da8eb >> 3

    はいその通りでして、当初SQLでやろうとして断念し、作業テーブルに書き出したものを、
    VBAで削除するしかできませんでした。

    すごいですね。これでできてしまうのですか!
    こちらを採用させていただきます。

    6

    下記のSQLでもskさんのクエリと同じ結果を得られます。
    メリットとしては、このクエリの場合は編集操作が可能です。
    デメリットとしては、データ数が多いとskさんのより重くなる可能性があります。

    SELECT Mtbl_社員.*
    FROM Mtbl_社員
    WHERE DCount("社員コード","Mtbl_社員","社員コード=" & [社員コード])>1;
    
    7
    はづき 2025/05/10 (土) 06:04:51 69f3e@da8eb >> 3

    ありがとうございます。
    最初、Dcountが直感的にはやりやすいので思い浮かびましたが、
    これまでの経験上、D系を使うとかなりストレスフルなのを感じていましたので、
    レコードが2万件くらいあるので、やりずらかったです(なので試してもいなかったです)。
    HAVINGのほうは、それほどストレスなく使えました。

    8
    hatena 2025/05/10 (土) 10:04:29 修正 >> 3

    抽出したデータの閲覧だけならskさんのサブクエリを使う方法でいいと思います。

    更新する必要があり、かつ、ストレスなく使いたいという場合は、私なら下記の方法をとります。

    下記のような[社員コード]のみの一時テーブルを作成しておきます。

    テーブル名: Tmp_兼任社員コード
    フィールド: 社員コード (主キー)

    下記のクエリを順次実行します。

    削除クエリ: 一時テーブルのデータを削除

    DELETE Tmp_兼任社員コード.*
    FROM Tmp_兼任社員コード;
    

    追加クエリ: 一時テーブルに兼任社員コードを追加

    INSERT INTO Tmp_社員コード ( 社員コード )
    SELECT 社員コード
    FROM Mtbl_社員
    GROUP BY 社員コード
    HAVING Count(*)>1;
    

    兼任社員抽出クエリ

    SELECT Mtbl_社員.*
    FROM Mtbl_社員 INNER JOIN Tmp_社員コード
     ON Mtbl_社員.社員コード = Tmp_社員コード.社員コード;
    

    やっていることはskさんのSQLのサブクエリ部分を一時テーブルにしただけです。
    これでストレスフリーで編集作業も可能になります。

    9
    はづき 2025/05/10 (土) 13:04:24 69f3e@da8eb >> 3

    確かにです、一時テーブルに社員コードだけを格納してINNER JOINですね。
    パフォーマンスを落とさず、クエリが読み取り専用になってしまう場合などは、有効ですね。