ACCESSのクエリで悩んでいます。ご回答頂けると幸いです。

<やりたいこと>
更新履歴を残しつつ、現在事項のみを抽出する作成クエリを作りたい。

<元テーブル : 履歴事項 >

ID│更新日 │コード│内容1  │内容2  │更新理由
01│4/22│001│あいうえお│かきくけこ│新規
02│5/22│002│さしすせそ│たちつてと│新規
03│5/22│001│なにぬねの│     │はひふへほ

更新があったときは、変更する内容だけを入力し、
変更のない内容はNULLにします。


<作成したいテーブル : 現在事項>

コード│内容1  │内容2  
001│なにぬねの│かきくけこ
002│さしすせそ│たちつてと

コードごとに更新日が最新のものを抽出し、ブランクの内容があったら、
その直近の更新日のものを抽出してくるようにしたいのです。


当方初心者のため、できればクエリのデザイン画面で
できる方法があるといいのですが、難しいならSQLも頑張ります。
ご回答、よろしくお願い致します。

A 回答 (1件)

クエリのSQLビューで以下を貼り付け実行してみるとどうなりますか。



SELECT T1.コード,
(SELECT TOP 1 Q1.内容1 FROM 履歴事項 AS Q1 WHERE Q1.コード=T1.コード AND Not Q1.内容1 Is Null ORDER BY Q1.更新日 DESC) AS 内容1,
(SELECT TOP 1 Q2.内容2 FROM 履歴事項 AS Q2 WHERE Q2.コード=T1.コード AND Not Q2.内容2 Is Null ORDER BY Q2.更新日 DESC) AS 内容2
FROM 履歴事項 AS T1
GROUP BY T1.コード;

直にテーブルを作成するのなら、FROM の前に INTO 現在事項 を入れてみてください。

この回答への補足

ご回答が遅くなって申し訳ありません。
丸写しはよくないと思うので、SQLを理解すべく頑張っているのですが、なかなか難しくて。もう少し頑張ってみます。お時間ください。

補足日時:2009/05/29 21:29
    • good
    • 0
この回答へのお礼

ありがとうございました。

ただ、やはりSQLが難しいのと、ブランクの内容があったらその直近の更新日のものを抽出となると、ブランクに変更することができなくなるので、更新日ごとにすべての内容を入れるようにして、クエリの2段重ねで作成しました。

クエリ1で、コードをグループ化し、更新日の最大で集計。
クエリ2で、クエリ1のコードと更新日に、履歴事項テーブルをくっつける。

これでなんとなくうまくいきました。
お騒がせして申し訳ありませんでした。

お礼日時:2009/05/30 12:37

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QAccessで更新履歴情報を保存(表示)する方法を教えてください。

Accessで、顧客管理を作っているのですが担当者が変更される事が多くあります。
この場合、データを上書き保存するのではなく、別ファイル(更新情報ファイル)に、変更前の情報を随時自動的に書き込んでいきたいのですが、どの様な方法があるか教えてください。

Aベストアンサー

ご指名ありがとうございますm(_ _)m

えぇ、前回(No.164850)の3番目の方法が良いとの事で・・・・

まず、担当者の変更履歴用のテーブル(担当者履歴)、重要人物の変更履歴用のテーブル(重要人物履歴)を用意します。
テーブルの中身(フィールド)は、担当者情報・重要人物情報のテーブルをコピーして、それに変更日時フィールド(日付/時刻型)を加えたものとし、更新日時フィールドの規定値を「Now()」としてください。
もし、元のテーブルでオートナンバー型を使用している場合は履歴用テーブルでは数値型に変更してください。

次に前回記述したコードの内、strSQL=・・・以降の部分を変更します。
(担当者変更時)
strSQL = "insert into 担当者履歴 select * FROM 担当者情報 " & _
  "where 担当者ID = " & Me.担当者ID

(重要人物変更時)
strSQL = "insert into 重要人物履歴 select * FROM 重要人物情報 " & _
  "where 重要人物ID = " & Me.重要人物ID

上記の場合、担当者・重要人物の格納してあるテーブルをそれぞれ担当者情報(主キー:担当者ID)、重要人物情報(主キー:重要人物ID)と仮定してあります。適宜変更してください。
また、今回のケースでフィールド数が同一であればUNIONを使用して一つのサブフォームに更新情報を表示することもできますが、同一でない場合やフィールド名の関係もありますので、それぞれを二つのサブフォームに表示してみる方法ではまずいでしょうか(^ ^;

ご指名ありがとうございますm(_ _)m

えぇ、前回(No.164850)の3番目の方法が良いとの事で・・・・

まず、担当者の変更履歴用のテーブル(担当者履歴)、重要人物の変更履歴用のテーブル(重要人物履歴)を用意します。
テーブルの中身(フィールド)は、担当者情報・重要人物情報のテーブルをコピーして、それに変更日時フィールド(日付/時刻型)を加えたものとし、更新日時フィールドの規定値を「Now()」としてください。
もし、元のテーブルでオートナンバー型を使用している場合は履歴用テーブルで...続きを読む

QACCESSでログを残す方法

お世話になっています。
ACCESS初心者ですがよろしくお願いいたします。

現在、勤務表を社員が各自で見れるようなシステムをアクセスで組んでいます。
いろんな人が見るのでACCESSにログが残せないかと、ネット上を探してみたところ詳しいことはのっておらず困っています。
残したいログはPC名、ユーザー名、社員ID、使用日、時間、使用内容です。
ACCESSを開いたときからログを取り始めたいです。
何かいい方法はありませんでしょうか?

ちなみにですが、今できていることは、データベースを表示しない。Shiftの無効・有効。ツールバーの非表示。です。
ACCESSを開くと最初にメニュー画面が出るようになっています。
メニューには明細票一覧ボタンとパスワード変更ボタン・終了ボタンとShiftの無効・有効のパスワード入力ボタンがあります。
明細票一覧・パスワード変更は社員IDとパスワードが一致しなければ入れないようになっています。

聞かれそうな情報はかいてみましたが足りないようでしたら申し訳ありません。
どうかよろしくお願いいたします。

Aベストアンサー

いい方法といいますか、提案です。
PC名、ユーザー名は各々、Environ("Computername") とEnviron("Username") で
得られます。使用日時は、Now()。
社員IDは・・・今やっている方法の延長で求めてもらうとして
ログを残すテーブル名を LOG とすると
たとえばメニューフォームの適当なイベントに
(開く時、閉じる時、どこかのコントロールがFocusを得た時など)
追加クエリを走らせることになると思います。
Application.Currentdb.Execute("INSERT INTO ~~
テーブルは非表示にしておく。
VBA完成の暁には必ず、MDBをMDE化して置くとかでしょうか。

QAccessで別テーブルの値をフォームに表示したい

初めてのAccessで分からない事があり質問させてください。

<会社テーブル>
会社ID
会社名
住所

<社員テーブル>
会社ID
社員名
ソート番号

*1社に対し複数の社員レコードが存在

以上のようなテーブルがあるとします

現在「会社テーブル」を表形式で一覧表示しています
会社ID,会社名、住所とフィールドが並んでいるのですが、その後ろに「社員テーブル」のソート番号が一番若い社員名を表示したいと考えています(現状は番号関係なく表示させる方法すら分かりません)

色々いじくりまわしたのですが、初めてAccessをさわる事もあってよくわかりません

リレーション等でひっぱってくる事ができるのでしょうか?

どなたか教えて頂けませんでしょうか

何卒よろしくお願い致します

PS.Access2013で作成中です

Aベストアンサー

単純にテーブル[会社]のみでフォームを作成し、社員表示用テキストボックスを追加。そして、そのプロパティを表示し

コントロールソース=DBLookup("SELECT 社員名 FROM 社員 WHERE 会社ID=" & [会社ID] & " ORDER BY ソート番号")

これは、以下の標準モジュールに登録したユーザ関数 DBLookup()を使っています。これで、クエリを用意しなくても目的を達成できます。

さて、かかるユーザ関数を標準ライブラリに登録したくない場合、

1、"社員ソートクエリ"を作成します。

SELECT 社員.会社ID, 社員.社員名
FROM 社員
ORDER BY 社員.ソート番号;

2、コントロールソースに次のように書きます。

=DLookUp("社員名","社員ソートクエリ","会社ID=" & [会社ID])

http://office.microsoft.com/ja-jp/access-help/HA001228825.aspx

DLookup()については、マイクロソフトの解説を参照されてください。

【DLookup()の限界を破るにはVBAで同じ関数を作るしかない】

マイクロソフトの解説を読めば判りますが、ORDER BY 節を指定する引数が用意されていません。ですから、どうしても、"社員ソートクエリ"を作成するという手間が必要となります。そこで、SQL文を引数とするDBLookup()をVBAで書けば、その手間を省けるという算段になります。この辺りは、好みと趣味の問題。どっちでも良いと思います。そういうお断りをした上で DBLookup()を紹介しておきます。なお、ADOは、つぎのように参照設定しないと利用できません。

http://www.happy2-island.com/access/gogo03/capter00307.shtml

Public Function DBLookup(ByVal strQuerySQL As String, _
             Optional ByVal ReturnValue = Null) As Variant
On Error GoTo Err_DBLookup
  Dim DataValue
  Dim rst     As ADODB.Recordset

  Set rst = New ADODB.Recordset
  With rst
    .Open strQuerySQL, _
       CurrentProject.Connection, _
       adOpenStatic, _
       adLockReadOnly
    If Not .BOF Then
      .MoveFirst
      DataValue = .Fields(0)
    End If
  End With
Exit_DBLookup:
On Error Resume Next
  rst.Close
  Set rst = Nothing
  DBLookup = IIf(Len(DataValue & ""), DataValue, ReturnValue)
  Exit Function
Err_DBLookup:
  MsgBox "SELECT 文の実行時にエラーが発生しました。(DBLookup)" & Chr$(13) & Chr$(13) & _
      "・Err.Description=" & Err.Description & Chr$(13) & _
      "・SQL Text=" & strQuerySQL, _
      vbExclamation, " 関数エラーメッセージ"
  Resume Exit_DBLookup
End Function

単純にテーブル[会社]のみでフォームを作成し、社員表示用テキストボックスを追加。そして、そのプロパティを表示し

コントロールソース=DBLookup("SELECT 社員名 FROM 社員 WHERE 会社ID=" & [会社ID] & " ORDER BY ソート番号")

これは、以下の標準モジュールに登録したユーザ関数 DBLookup()を使っています。これで、クエリを用意しなくても目的を達成できます。

さて、かかるユーザ関数を標準ライブラリに登録したくない場合、

1、"社員ソートクエリ"を作成します。

SELECT 社員.会社ID, 社員.社員名
FR...続きを読む

QACCESS 一番最新の日付の金額を出したいのですが・・

社員ID/交通費/登録日 のフィールドがあるテーブルがあります。

社員ID/交通費/登録日
0001  800  2007/4/1
0002  400  2007/4/2


0001 700  2007/5/2

となった場合、0001の人は700円と言う風に登録日が最新のものを抽出したいのですが

クエリをつくり登録日の集計を「最大」にしてみたら、日付は5/2がちゃんと出ますが、金額がその登録日以外の金額になるのです。

どうすればよいでしょうか?
分かる方教えて下さい。宜しくお願いします。

 

Aベストアンサー

SQL文とクエリは同じです。

フィールド:登録日
テーブル:TEST
並び替え:
表示:
抽出条件:DLOOKUP("MAX(登録日)","TEST","社員ID=" & 社員ID);
または:

フィールド:登録日
テーブル:TEST
並び替え:
表示:
抽出条件:(SELECT MAX(登録日) FROM TEST AS B WHERE TEST.社員ID=B.社員ID)
または:

このように、クエリを編集すれば良いということです。
ですから、事実上は、"TEST" だけを実際のテーブル名、クエリ名に置き換えるだけです。

QACCESSでフォームを使って、テーブルを参照、データ入力、データ更新をしたいのです

フォームを使って、テーブルを参照、データ入力、データ更新をしたいのです。

売上テーブル

 ID   商品コード  日付    金額 
 1    G1     20080101  532153
 2    G1     20080101  564281
 3    G1     20080301  538123
 4    J4     20080301  124531
 5    J4     20080302  125483

ID:オートナンバー 商品コード:数値型 日付:数値型 金額:数値型

これを使い、
フォームではまず

レコードナンバーを入力画面
       ↓
レコード番号を入れると、そのレコードのデーターが画面に表示され、
その画面で修正可能
       ↓
 保存 ボタンで保存

という流れです。

レコードナンバーはIDを使おうと思っています。

データの量が莫大な為、コンポボックスなどは使えません。

できるだけ、VBAなどは使わずに作りたいです。

よろしくお願い致します。

フォームを使って、テーブルを参照、データ入力、データ更新をしたいのです。

売上テーブル

 ID   商品コード  日付    金額 
 1    G1     20080101  532153
 2    G1     20080101  564281
 3    G1     20080301  538123
 4    J4     20080301  124531
 5    J4     20080302  125483

ID:オートナンバー 商品コード:数値型 日付:数値型 金額:数値型

これを使い、
フォームではまず

レコードナンバーを入...続きを読む

Aベストアンサー

まずそのテーブルを基にしてフォームを作成します。
そのフォームのヘッダー部分にテキストボックスを配置後、一旦
上書き保存。
フォームのレコードソースを
SELECT *
FROM テーブル名 WHERE ID=[Forms]![フォーム名]![テキストボックス名]
とします。
次にテキストボックスの更新後処理に
Me.Requery
とすれば完成です。
フォームを開いてテキストボックスにID入力後エンターしてください。

保存に関しては、コマンドボタン作成後クリック時イベントに
DoCmd.RunCommand acCmdSaveRecord
とすれば良いでしょう。

この手のモノは検索すれば相当数ヒットするので、そちらを参考にされるのもよろしいかと。

QAccess 別テーブルにある値を抽出条件にしたい

OS:WindowsXP SP3
使用ソフト: Microsoft Access2003


選択クエリにて、別テーブルのフィールドにある値すべてを抽出条件にできますか?


ホームページに来て頂いた方の検索キーワードを集計しております。
テーブル1には『検索キーワード履歴』フィールドがあり、お客様が使用した検索キーワードが入力されています。(約2万件)
テーブル2には『除外キーワード候補』フィールドがあり、不要なキーワードが入力されています。(約10件)


クエリにて、『検索キーワード履歴』から『除外キーワード候補』の値を全て除いた結果を出力させたいのですが、
抽出条件をどのように指定したらいいのか分かりません。

そもそも、別テーブルのフィールドにある値すべてを除外させる抽出条件って指定できるのでしょうか。
SQLを用いる方法でも構いませんので教えてください。

Aベストアンサー

SELECT * FROM テーブル1
WHERE NOT EXISTS
(SELECT * FROM テーブル2 WHERE テーブル1.検索キーワード履歴 = テーブル2.除外キーワード候補)
OR 検索キーワード履歴 IS NOT NULL
とか
SELECT * FROM テーブル1
WHERE 検索キーワード履歴 NOT IN (SELECT 除外キーワード候補 FROM テーブル2 )
ということ?
1フィールドに1キーワードの場合です。

QAccess 同じデータをたくさんのレコード(同一列)に一度に入力するには

いつもお世話になっています。
Accessの基本的な入力に関して教えてください。
同じデータをたくさんのレコード(同一フィールド)に一度に入力するには、どうすればよいか教えてください。

Excelの列方向へのコピーと同じような感覚でできないのでしょうか?

よろしくお願いします。

Aベストアンサー

質問の回答にならないかも知れませんが・・・

1.EXCELでコピーするための元データを作成します
  ※仮にレコードが1000件ある場合はEXCELで1000行作ります。

2.Excelのデータをコピーします。

3.Accessのテーブルを開きます。

4.先頭レコードの貼り付けをしたい項目にカーソルを合わせます。(カーソルは白の十字)

5.下方向へドラッグし、項目を選択します。

6.貼り付けをします。

※貼り付けに失敗した場合、元に戻せませんので必ず元ファイルのコピーを取ってから行ってください

よろしければ、お試し下さい

QACCESSで空白のデーターをクエリで判定/識別する方法を教えてくださ

ACCESSで空白のデーターをクエリで判定/識別する方法を教えてください。
EXCELでは空白を""で判定/識別表していますがACCESSではどうなるのでしょうか。

下の例はフィールドに試験番号があればその番号を、空白なら”欠席”と表示しようとしています。
IIf(([試験番号]="空白の場合何を入れる?"),[試験番号],"欠席")

Aベストアンサー

もうひとつの書き方は
式1: IIf([試験番号] Is Not Null,[試験番号],"欠席")
第2、第3引数の、質問の順序にあわせるとこうなる。

QACCESS IIF関数 複数条件の設定について

 選択クエリにおいて、あるフィールド「 X」 のレコード数値が
 
  0<[X]<=50   であれば A 
  50<[X]<=100  であれば B 
  100<[X]<=150  であれば C

 と表記させるフィールド「Y」を追加したいと考えています。
 この場合、Yのフィールド設定で指定する数式についてご教授願います。

 一応、
  IIf(0<[X]<=50,"A","") Or IIf(50<[X]<=100,"B","") Or IIf(100<[X]<=150,"C","")

  としましたが、実行すると、Yの列がすべて「-1」と表記されてしまいます。

 何卒よろしくお願いいたします。

Aベストアンサー

a)IIF関数で対応する場合:
 IIF関数の第2引数または第3引数に、IIF関数を入れ子とする必要があります。

式: IIF([X]<=0, "", IIF([X]<=50, "A", IIF([X]<=100, "B", IIF([X]<=150, "C", ""))))


b)別の組込関数を使用する場合:
 IIF関数は二択ですので入れ子にする必要がありますが、Accessのクエリで
 使用できる、似た機能の関数に、Switch関数というものもあります。
 これであれば、入れ子にする必要がなくなります。
 (詳しくは、Accessのヘルプを参照下さい)

式: Switch([X]<=0, "", [X]<=50, "A", [X]<=100, "B", [X]<=150, "C", True, "")


なお、数学あるいは一般生活では確かに「0<[X]<=50」という表記をしますが、
Accessの関数などではこれだと正しい結果が得られません。
正しく認識させるためには、等号・不等号を挟んだ式は、「左辺」と「右辺」の
2つの要素からなる形にする必要があります。
(「0<[X]<=50」は「[X]>0 And [X]>=50」と分割してやる、と)

但し、今回のご質問のような『連続した範囲』であれば、前(左)で既出となる
式の要素で「[X]<=0」が「真(=-1)」とならなかった時点で、「[X]>0」が保証
されますので、上記のように、「[X]>0」を省略して「[X]<=50」だけを条件として
指定すればOk、ということになります。
(「0<[X]<=50」の次が「80<[X]<120」などのように、「50~80」が欠けた
 場合は、省略ができない、と)


【参考】
「0<[X]<=50」は、このままだと「0 < ([X]<=50)」という式と解釈されます。
この場合、「[X]<=50」は、「真(=-1)」か「偽(=0)」か「Null」のいずれかに
なります。
何にせよ、「0<[X]<=50」全体として「正(=-1)」となることがないため、
ご質問の式では、IIF関数は常に第3引数に指定された値「""」を返す
ことになります。

この結果、式全体としては「"" Or "" Or ""」という形となり、「0かNull」
以外なので、「真(=-1)」という値が返された、ということです。

なお、Nullについては、以前、他の方の質問につけた回答も、併せて参考までに:
http://oshiete.goo.ne.jp/qa/4850675.html

a)IIF関数で対応する場合:
 IIF関数の第2引数または第3引数に、IIF関数を入れ子とする必要があります。

式: IIF([X]<=0, "", IIF([X]<=50, "A", IIF([X]<=100, "B", IIF([X]<=150, "C", ""))))


b)別の組込関数を使用する場合:
 IIF関数は二択ですので入れ子にする必要がありますが、Accessのクエリで
 使用できる、似た機能の関数に、Switch関数というものもあります。
 これであれば、入れ子にする必要がなくなります。
 (詳しくは、Accessのヘルプを参照下さい)

式: Switch([X]<=0, "", [X]<=50, "A"...続きを読む

QAccessで最新のレコードを抽出するには

お世話になります。

このようなテーブルがあるとします。

No|日時     | 部門  | 更新内容 
--+------------+--------+----------
1 |04/12 12:21:35| A部門 | 更新C
2 |04/07 09:15:05| B部門 | 更新う
3 |04/19 08:23:45| A部門 | 更新A
4 |04/05 10:15:20| B部門 | 更新あ
5 |04/20 09:20:13| B部門 | 更新い
6  |04/02 09:20:15| A部門 | 更新B

この中から部門毎にグループ化して
部門毎に日時の最新のデータ

No|日時     | 部門  | 更新内容 
--+------------+--------+----------
3 |04/19 08:23:45| A部門 | 更新A
5 |04/20 09:20:13| B部門 | 更新い

を抜き出すクエリの作り方を教えてください。
ちなみに今困っているDBの更新内容に相当するフィールドは50フィールドほどあります。
よろしくお願いします。

多分クエリの集計を使用すると思っています。
多少ですがSQLわかります。
多少ですがVBAわかります。

お世話になります。

このようなテーブルがあるとします。

No|日時     | 部門  | 更新内容 
--+------------+--------+----------
1 |04/12 12:21:35| A部門 | 更新C
2 |04/07 09:15:05| B部門 | 更新う
3 |04/19 08:23:45| A部門 | 更新A
4 |04/05 10:15:20| B部門 | 更新あ
5 |04/20 09:20:13| B部門 | 更新い
6  |04/02 09:20:15| A部門 | 更新B

この中から部門毎にグループ化して
部門毎に日時の最新のデータ

No|日時     |...続きを読む

Aベストアンサー

SQLを考える時は理論の組み立てが肝要です。
(1)部門別に日時の最大値を求める。
(2)テーブルから、部門と日時が(1)と同じものを求める。
厄介なのは英語だから逆になることです。

SELECT A.* FROM テーブル AS A INNER JOIN
(SELECT 部門,MAX(日時) AS 日付 FROM テーブル
GROUP BY 部門) AS B
ON A.部門=B.部門 AND A.日時=B.日付

()の中のサブクエリが(1)になります。外側のSELECTが
(2)に該当します。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報