• ベストアンサー

アクセスでデータを集計するには

例として、下記のデータテーブルを受け取りました。 テーブル1 ID 名前 項目 値 01 AA 住所 ○○ 01 AA 電話 ○× 01 AA 月給 ○△円(テキスト) 01 AA 手当 ○□円(テキスト) 02 BB 住所 □□ 02 BB 電話 □× 02 BB 月給 □△円(テキスト) 02 BB 手当 □○円(テキスト) 03 CC 住所 ×☆ 03 CC 電話 ×○ 03 CC 月給 ×△円(テキスト) 03 CC 手当 ×□円(テキスト)  以下続く 上記表を、下記表 テーブル2 ID 名前 住所 電話 月給    手当 01 AA ○○ ○× ○△(数値) ○□(数値) 02 BB □□ □× □△(数値) □○(数値) 03 CC ×☆ ×○ ×△(数値) ×□(数値)  以下続く のように編集された表を新たに作成したいのですが、どのようにしたらよろしいのでしょうか(質問1)。  また、テーブル2から、月給+手当が□△以上の人のIDと名前を抽出できるようにするには、どのような操作が必要なのでしょうか(質問2)。  データはテーブル1の形式で定期的に送られて来た上、データは全てテキスト形式故、テーブル2の形式に再編集したテーブルがあった方がいいと思いました。  アクセスは今まで使ったことがありません。  恐らくご回答の解説が長くなってしまうでしょうから、作り方の概要と流れだけでも構いません。もちろん詳細にご回答賜れば誠に幸いです。  以上、よろしくご回答のほど、お願い申し上げます。

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

  • ベストアンサー
  • Euglena
  • ベストアンサー率62% (5/8)
回答No.2

厳密にいうと正確ではないのですが、 ID、名前、項目で重複したレコードがないことを前提とすると、 ACCESSのクロス集計クエリーを使用すればできると思います。 ・クロス集計クエリーで、   ID、名前を行見出し   項目を列見出し   値を先頭の値  で定義 このままだと月給と手当がテキストのままなので、 テーブル作成クエリーを新たに作成して数値に変換。 テーブル作成クエリーを実行させれば目的のテーブルができると思います。 データ抽出は、条件文に 「月給+手当が***円より大きい」 と記述してやればできるはずです。 SELECT ID,名前 FROM 作成テーブル WHERE 月給+手当 > ***

zinchan
質問者

お礼

 すぐご報告できず、申し訳ありません。  おかげさまで、ご教示下さいました方法でできました。  11/15にアクセスの関数辞典を購入し、やり方を理解しました。手当名とテキストの数値の間に空白文字があることを利用し、選択クエリーのデザインビューフィールドに、 Val(Replace(Replace(Mid([○手当],InStr([○手当]," ")+1,Len([○手当])),",",""),"%","")) としたら、「,」が取れた数値だけ抽出され、計算可能になりました。  そして、やっと11/16に目的の抽出一覧表を作成することができました。  ここまでの段階までお導き下さり、誠にありがとうございました。

zinchan
質問者

補足

 ご回答下さりありがとうございます。  ご回答のとおり、クロス集計クエリーを新規に構成し、ご指示どおりの定義を行い、質問のテーブル2に相当するクロス集計クエリーを作成することができました。  ご指摘のとおり、値がテキストのままですので、テーブルを作成するためのクエリーを、どうやって作ったらよいのかわからぬまま、とりあえず選択クエリーで構成しようと作りましたが、どのようにしたらテキストを数値に変換できるのかわかりません。  例えば、値の覧に、「資格 28000円」、「時間外 30027円」と入ってしまっている場合、どのように数値だけを抽出したらよろしいのでしょうか。

その他の回答 (5)

  • Euglena
  • ベストアンサー率62% (5/8)
回答No.6

忘れてました。 モジュールの作成画面で「ツール」→「参照設定」を選び、 「Microsoft DAO *** Object Library」 という項目にチェックを入れてください。 そうしないと、 dim DB as Database の行でエラーが出ます。

zinchan
質問者

お礼

 私の疑問点に一つ一つご丁寧にご教示下さり、誠にありがとうございました。  今から思うと、別の質問として項目を立てた方がよかったと、申し訳なく思います。  今後、私にとってのアクセスの先生として、心にとどめておきたく思います。  ありがとうございました。

  • Euglena
  • ベストアンサー率62% (5/8)
回答No.5

とりあえずこんな感じでしょうか・・ Public Function 集計() Dim DB As Database Dim TBL1 As DAO.Recordset Dim TBL2 As DAO.Recordset Dim 月給 As Long Dim 手当 As Long Dim 住所 As String Dim 電話 As String 'データベース指定 Set DB = CurrentDb '元テーブルオープン Set TBL1 = DB.OpenRecordset("テーブル1", DB_OPEN_SNAPSHOT) 'レコードがあったら処理開始 If TBL1.RecordCount <> 0 Then   '1番目のレコードを取得   TBL1.MoveFirst   '読み取るレコードがなくなるまで回す   Do Until TBL1.EOF     '書き込むテーブルに同一IDのデータがあるか?     SQL = "select * from テーブル1集計 where ID = '" & TBL1![ID] & "'"     Set TBL2 = DB.OpenRecordset(SQL, DB_OPEN_DYNASET)     If TBL2.RecordCount <> 0 Then       'レコードがあったので更新処理       '初期値として登録されているデータをセット       住所 = TBL2![住所]       電話 = TBL2![電話]       月給 = TBL2![月給]       手当 = TBL2![手当]       If TBL1![項目] = "住所" Then         '項目が「住所」ならば住所のデータを書き換え         住所 = TBL1![値]       ElseIf TBL1![項目] = "電話" Then         '項目が「電話」ならば電話のデータを書き換え         電話 = TBL1![値]       ElseIf TBL1![項目] = "月給" Then         '項目が「月給」ならば月給のデータを書き換え         月給 = 数値抽出(TBL1![値])       ElseIf TBL1![項目] = "手当" Then         '項目が「手当」ならば手当のデータを書き換え         手当 = 数値抽出(TBL1![値])       End If       'レコード更新       TBL2.Edit       TBL2![住所] = 住所       TBL2![電話] = 電話       TBL2![月給] = 月給       TBL2![手当] = 手当       TBL2.Update     Else       'レコードがないので追加処理       '初期値セット       住所 = ""       電話 = ""       月給 = 0       手当 = 0       If TBL1![項目] = "住所" Then         住所 = TBL1![値]       ElseIf TBL1![項目] = "電話" Then         電話 = TBL1![値]       ElseIf TBL1![項目] = "月給" Then         月給 = 数値抽出(TBL1![値])       ElseIf TBL1![項目] = "手当" Then         手当 = 数値抽出(TBL1![値])       End If       'レコード追加       TBL2.AddNew       TBL2![ID] = TBL1![ID]       TBL2![名前] = TBL1![名前]       TBL2![住所] = 住所       TBL2![電話] = 電話       TBL2![月給] = 月給       TBL2![手当] = 手当       TBL2.Update     End If     TBL2.Close     '次のレコードを取得     TBL1.MoveNext   Loop End If TBL1.Close DB.Close End Function Public Function 数値抽出(対象文字列 As String) As Long '「×× 99999円」というパターンオンリーで・・ Dim 文字列長 As Long Dim i As Long Dim 検査文字 As String Dim 抽出文字列 As String 抽出文字列 = "" 文字列長 = Len(対象文字列) For i = 1 To 文字列長   検査文字 = Mid(対象文字列, i, 1)   If Val(検査文字) > 0 Then     抽出文字列 = 抽出文字列 + 検査文字   End If Next 数値抽出 = Val(抽出文字列) End Function

zinchan
質問者

お礼

上記プログラムを組むと、後で更新時に楽になり、大変よいかとは思いますが、エクセルであれば理解しやすかったのですが、アクセスでは、私のレベルではまだ難しいようです。  今後、勉強して、よりスマートなものを作成できるよう、これから頑張りたいと思います。  ありがとうございました。

  • Euglena
  • ベストアンサー率62% (5/8)
回答No.4

あ~、すみません。 先頭に「資格」などの文字が入っているのですね。 そうするとVal()は使えませんね・・ モジュールで関数を作らないといけないですかねぇ。 話はそれますけど、 「資格」とか「残業」って、「手当」の項目になると思いますけど、 提示されている表ですと、どちらかしか入らない気がしますが・・

zinchan
質問者

補足

 ご懇切なご回答誠にありがとうございます。 >話はそれますけど  例として出した表は、あくまでも説明のために簡便に表したまでで、実は1つのIDに対してもっと多数の項目があります。手当の項目についても、各種手当があり、それらに対応する項目名は各IDごとに全て覧が設定され、それぞれの行に入っています。手当受取対象者でなくとも値には「-円」と入力されています。ごく一部の項目で、値の覧に各種手当名と金額が併記されているのです。  val()で変換できそうな項目は多数あります。  先程の捕捉を記入後確認したら、本回答の他、モジュール関数の定義方法等、極めて詳細かつご懇切なご回答を賜り、深く感謝いたします。今日はもうできないので、後日検討させていただきます。

  • Euglena
  • ベストアンサー率62% (5/8)
回答No.3

数値への変換は、 Val([※※※].[月給]) AS 月給 (※※※はクロス集計クエリー名) と、Val関数を使用すればいいと思います。 Val関数は先頭から変換を行っていって、 変換できない文字が出てきたら終了しますので、 後ろに「円」がついていても大丈夫でしょう。

zinchan
質問者

お礼

 こちらの疑問に早速ご回答下さりありがとうございました。No.2礼に上げた式で計算可能な数値を取り出すことができました。式を入力する場所もわかりました。  本当にありがとうございました。

zinchan
質問者

補足

 早速のご回答ありがとうございます。  とりあえず作成したクロス集計クエリーの選択クエリーの抽出条件の覧に、上記変換式を入力(そのままでは式の型が一致しないと言われたので、Val関数内の.は,に変えました)してみましたが、式の最後のカッコの位置で、「指定した式に含まれる関数で、引数の数が一致しません」とまたまた怒られてしまいました。  Val関数のヘルプを探してみましたが、見つけられませんでした。とても悲しいです。  たびたび大変申し訳ございませんが、Val関数の書式をもう一度ご解説願いたいのと、式をどこに入力すればいいのか、ご教示下さいますでしょうか。

  • souta_n
  • ベストアンサー率33% (79/234)
回答No.1

ちょっと項目を減らして解説します。 ID 名前 項目 値 01 山田 住所 大阪 01 山田 電話 06 01 田中 住所 京都 01 田中 電話 075 03 加藤 住所 神戸 03 加藤 電話 078 というテーブルを元テーブルを(T_元)とします。 コンバート先のテーブルを次のようにフィールドを設けて作成します。これを(T_コンバート)とします。 ID 名前 住所 電話  1.下記の様な標準モジュールを1つ作成し実行します。 これはDAOという機能を使っていますが、Access97は既定で使用できますが、Access2000の場合は、ツールメニューの参照設定でMicrosoftDAO*.*ObjectLibraryを参照させておく必要があります。Access2002はそのまま出来たと思いますが、ちょっと記憶が定かじゃないです。 Sub Conv() Dim DB As Database Dim RS1 As Recordset Dim RS2 As Recordset Set DB = CurrentDb Set RS1 = DB.OpenRecordset("T_元", dbOpenTable) Set RS2 = DB.OpenRecordset("T_コンバート", dbOpenTable) Do Until RS1.EOF RS2.AddNew RS2!ID = RS1!ID RS2!名前 = RS1!名前 If RS1!項目 = "住所" Then RS2!住所 = RS1!値 ElseIf RS1!項目 = "電話" Then RS2!電話 = RS1!値 End If RS2.Update RS1.MoveNext Loop RS1.Close RS2.Close DB.Close End Sub 2.実行後のT_コンバートには下記の様なデータが入ります。 ID 名前 住所 電話  01 山田 大阪 01 山田    06 02 田中 京都 02 田中    075 03 加藤 神戸 03 加藤    078 3.あとはクエリーなどを使って集計してみたらと思います。

zinchan
質問者

お礼

 ご教示下さいましたとおり組むと、後で更新時にも楽になり、大変よいかとは思いますが、エクセルであれば理解しやすかったのですが、アクセスでは、私のレベルではまだ難しいようです。  ご回答を下さいましたときは、アクセスのデータベース構築の流れさえもわかっておらず、おかげさまで勉強するとっかかりをつかむことができました。  また、あれやこれやで目的の集計をすることができるようになりました。  今後、勉強して、上記のようなものを作成できるよう、これから頑張りたいと思います。  ありがとうございました。

zinchan
質問者

補足

 早速のご回答ありがとうございます。  コンバート先のテーブルを作成し、モジュールも訳がわからないながらご説明下さったように(テーブル名を当方の様式に替えて)作成しました。実行をかけてみましたが、上から2行目のDim DB As Databaseの行で止まってしまい、コンパイルエラー ユーザ定義型は定義されていませんと怒られてしまいました。  ヘルプを見ても、訳がわかりません。  アクセスはver.2002です。  どのように直していったらいいのか、ご指導下さいますと幸いです。

関連するQ&A

  • アクセスの集計について

    アクセスのクエリで、伝票番号でグループ化し、その横に、商品番号を並べたいです。 ★元テーブル★(名前:商品テーブル) 伝票番号 商品番号 1163069 AA01232 1168453 AAAA674 1168453 BBBB916 1174348 AA04041 1174348 BB04045 1174348 CC04041 ★作りたい状態★ 伝票番号 新商品番号 1163069 AA01232 1168453 AAAA674、BBBB916 1174348 AA04041、BB04045、CC04041 ★現状★ 伝票番号 新商品番号 1163069 AA01232、AA01232 1168453 AAAA674、BBBB916 1174348 AA04041、CC04041 SQLは、 SELECT 商品テーブル.伝票番号, First([商品番号]) & "、" & Last([商品番号]) AS 新商品番号 FROM 商品テーブル GROUP BY 商品テーブル.伝票番号; です。 first、lastが別に使いたいわけじゃないのですが、 他に方法がわからなくて使いました。 しかし、これだと、2つまでしか表示できないし、1つのものも 2つ表示されてしまって困っています。 わかりにくい質問で申し訳ありませんが、教えてください(^^)

  • 二つのデータを一つにデータにしたい

    題名の通りです。 二つのシートに、個人のデータが入っています。 二つのシートの両方に入力されている人もいれば、片方にしか入力されてない人もいます。 この二つのシートのデータから、一つの、全員のデータの入ったシートを作りたいのですが、何か良いやり方はないでしょうか? もちろん、両方に入力されている人は、一つのデータです。 また、項目も片方にしかない項目と、両方にある項目があります。 数が多いため、手入力だと時間がかかってしまいますので・・・ 文だと説明しにくいので、図を書いてみます。 シート1 ID 名前 住所 〒 1   A  AA 111-11 2   B  BB 222-22 4   D  DD 444-44 シート2 ID 名前 住所 年齢 1   A  AA 11 3   C  CC 33 5   E  EE 55 これを シート3 ID 名前 住所 〒   年齢 1   A AA 111-11  11 2   B BB 222-22 3   C CC      33 4   D DD 444-44 5   E EE       55 としたいので、『データの統合』機能は試してみたのですが、数字じゃないと、うまくいかないようだったので・・ すみませんが、宜しくお願いします。 また、長い文、読んでくれてありがとうございます。

  • access table 上書きしてデータ追VBA

    access365 名簿accdbにおいて テーブル1に ID 名前 住所 郵便番号 という項目があり IDは重複不可 数値 テーブル2に ID 名前 住所 郵便番号 という項目があり IDは重複不可 数値 と ふたつのテーブルがあるとき 追加クエリーで テーブル1に テーブル2のデータを追加するときは 同一のIDでは 上書きができません テーブル2のIDが テーブル1にまだ存在しないIDの数値であれば 追加クエリーにより データの追加ができますが 例えばIDが3の人物がいて そのテーブル1の住所が東京で これが新しいデータの格納されているテーブル2では ID3の住所が千葉となったときに これを追加クエリーでIDを3として上書きはできない構造のようです 更新クエリー というのも調べてみましたが ある一定の規則でたとえば物品の値段が100円増しのような 一定の更新条件がある場合であれば更新クエリーが使えますが 上の例のようにテーブル2においてテーブル1にもすでに名前の登録のあるIDのひとの 数人が住所がテーブル2において 新しいものとして変更されていて それをテーブル1に一括で住所の変更のできるVBA 御教示いただけますか (上記の場合ですと住所の変更と郵便番号の変換が同時に当然起きえます) また 同時に テーブル1にはIDの登録もまだない新規IDのひとも テーブル2に存在するとします 要は テーブル2には テーブル1にすでにID人物登録のあるひとと 新規IDのひとが混在している条件で、作りたいと思います すみませんが、おちから頂けると助かります 宜しくお願い致します office365 win10

  • group byを使う時に条件をつけたいです。

    どう頑張っても思いどうりにDBからデータがとれず困ってます... 例えばこんなテーブルがあったら(テーブル名が"test"、カラムが"name"と"id") table test name | id ---------- aa | 1 aa | 1 aa | 1 bb | 1 bb | 1 aa | 0 aa | 0 cc | 0 カラム"id"が0の時は、カラム"name"のgroup byせず カラム"id"が1の時だけ、カラム"name"のgroup byするには、どうすればいいのでしょう? このような感じにデータを取り出したいのです。 name | id  | COUNT ---------- aa | 1 | 3 bb | 1 | 2 aa | 0 | 1 aa | 0 | 1 cc | 0 | 1 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 最後のデータを含むレコード1行 MYSQL

    お世話になります。 最後の日にちを含むレコード全ての抽出方法がどうしてもわかりません。 id name date amount 1 AA 3/1 5 2 BB 3/1 5 3 CC 3/1 5 4 AA 3/2 7 5 BB 3/2 4 6 AA 3/3 1 これを、select * from テーブル group by name とすると、 id name date amount 1 AA 3/1 5 2 BB 3/1 5 3 CC 3/1 5 select id, name, max(date),amount from テーブル group by name とすると、 id name date amount 1 AA 3/3 5 2 BB 3/2 5 3 CC 3/1 5 望んでいる結果はこうです。最後のdateを含むレコード全てです。 id name date amount 3 CC 3/1 5 5 BB 3/2 4 6 AA 3/3 1 select * from テーブル as a where a.date=(select max(b.date) From テーブル as b where a.id=b.id); このようにしましたが、データの数が膨大なのですごく時間がかかってしまいます。 他、シンプルな方法はないでしょうか。 よろしくお願いします。 MYSQL バージョン5.0.45

  • accessのクエリーで、レコードを分割したい。

    テーブルに担当者 品名 数量      鈴木  A   100      佐藤  B   50とあります。 これを  鈴木  aa 100の10%で10      鈴木  bb   100の60%で60      鈴木  ㏄   100の30%で30      佐藤  aa 50の10%で5      佐藤  bb   50の60%で30      佐藤  ㏄   50の30%で15 という風にしたいです。 10% 60% 30%の数値は、変わりません。どうすればいいでしょうか。ご教授お願いいたします。

  • 特定のデータ同士の集計はできますか?

    どうしても自分で解決できません。 どなたか教えてください!! windows-xp,アクセス2003を使っています。 テーブルAには、フィールド名「実績ID」「A賞」「B賞」「C賞」「効果金額」という表になっており、データが1万件近くあります。データ型は数値型です。 もうひとつのテーブルBにも、同じくフィールド名「実績ID」「A賞」「B賞」「C賞」「効果金額」というものがあり、データ型は数値型です。 そこで質問です。 テーブルBのデータをテーブルAに加算したいのですが、何かよい方法はないでしょうか? テーブル同士の加算は基本的にはむりだとしたら、テーブルBの方をクエリにして加算する。という方法はいかがでしょうか? ちなみに、テーブルBのデータは、テーブルAにデータを加算したら、データを削除するようにしていきたいと思っています。 すみませんが、宜しくお願い致します。

  • access2010  同一idを列に追加

    access2010についてselectの方法を教えてください。 ↓元テーブル id | name 1 | a 1 | b 2 | aa 2 | bb 2 | cc 取得したい内容 id| name1| name2| | name3 1| a | b| 2| aa | bb | cc アクセスとエクセルのマクロを駆使していますが、うまくできません。

  • エクセルの集計計算について教えてください

    期間を指定するとデータを引っ張ってきます データは1000~2000件程存在します Aセル=名前 Bセル=略号 Cセル=日時 Dセル=場所 Eセル=不良合計 名前    略号       日時            場所    不良合計 A0001     AA   2014/06/01 00:04:28   1     7 A0010     BB   2014/06/01 00:18:10   2     3 A0011     DD   2014/06/01 00:29:35   4     8 A0001     EE   2014/06/01 00:24:55   2     9 A0005     CC   2014/06/01 00:29:35   3     4 A0010     BB   2014/06/01 00:27:09   2     6 A0020     AA   2014/06/01 00:32:13   1     4 A0001     AA   2014/06/01 00:33:26   3   3 A0020     EE   2014/06/01 00:37:31   5  17 A0016     FF   2014/06/01 00:47:22   6   7 A0030     BB   2014/06/01 00:54:35   2   3 A0015     AA   2014/06/01 01:01:11   1   2 A0001     DD   2014/06/01 01:03:01   4   8 A0020     EE   2014/06/01 01:06:21   5   11 A0011     BB   2014/06/01 01:08:19   2   4 A0005     DD   2014/06/01 01:17:20   4     13 A0011     BB   2014/06/01 01:22:41   2   8 A0016     AA   2014/06/01 01:23:47   1   2 A0010     CC   2014/06/01 01:25:08   3   11 .... 名前が同じ物でも、場所が異なると略号が変わってしまいます。 流れとしてはA001の物が場所1→2→3と進んで行きます。    名前   略号         日時         場所      不良合計 A0001   AA   2014/06/01 00:04:28   1   2 A0001   BB   2014/06/01 01:04:28   2   4 A0001   CC   2014/06/01 02:04:28   3   8 A0001   DD   2014/06/01 03:04:28   4   10 不良合計に関しては、前の物が加算されていく形になっています。 数千あるこのようなデータを今手計算で、場所毎の不良数を求めています。 例を挙げますと、上の4つのデータの場合 DDの不良合計とCCの不良合計を引いて、DDの不良合計は2 CCの不良合計とBBの不良合計を引いて、CCの不良合計は4 BBの不良合計とAAの不良合計を引いて、BBの不良合計は2 A0001   AA   2014/06/01 00:04:28   1   2 A0001   BB   2014/06/01 01:04:28   2   2 A0001   CC   2014/06/01 02:04:28   3   4 A0001   DD   2014/06/01 03:04:28   4   2 と言う形に手計算で置き換えてします。 ただ、数が膨大であり、名前に関しても同じ名前が1つではなく複数使われている事もあり計算が大変です。 何とか楽に計算する方法はないでしょうか? VBA?を使用してでもいいので、短時間で出来る集計方法があれば教えてください。

  • 【Access】SQL文教えてください!

    基本的な質問かもしれませんが・・・ テーブル名:test フィールド名:aa,bb,cc,dd,ee,ff (すべて数値型) aa~ccの合計からdd~ffの合計までの間を抽出したいのです。 どう書けばいいんでしょう?

専門家に質問してみよう