Accessのsql(ロジック)について伺います

このQ&Aのポイント
  • AccessのローカルDB(ADO)へSQL接続するプログラムを作成し、マスタTBLから最繁日3日分の全レコードを抽出し、別のテーブルへ登録したい。
  • 抽出には時分秒も必要であり、さらに時間別かつコード別の件数を求めるため、2段階に分けて処理を行う予定。
  • 現在のSQLでは、group byで結果をまとめてしまい、全レコードを羅列できない。また、時分秒を省いてしまうと第2段階の処理が行えない。
回答を見る
  • ベストアンサー

Accessのsql(ロジック)について伺います

Access mdb内でローカルDB(ADO)へSQL接続を行うプログラムを組んでおります。 ■テーブル:マスタTBL | 年 | 月 | 日 | 時 | 分 | 秒 | コード | +---- +-- +-- +-- +--+---+------+ | 2013 | 10 | 31 | 10 | 05 | 20 | A1234 | | 2013 | 10 | 31 | 10 | 10 | 00 | B1234 | | 2013 | 11 | 01 | 00 | 00 | 01 | A1234 | | 2013 | 11 | 01 | 00 | 00 | 01 | A1234 | | 2013 | 11 | 01 | 00 | 00 | 01 | A1234 | | 2013 | 11 | 22 | 05 | 10 | 09 | C1234 | | 2013 | 10 | 31 | 00 | 10 | 00 | B1234 | | 2013 | 10 | 31 | 22 | 46 | 55 | A1234 | ※後の作業都合上、日付も含めカラムは全て"文字列"です。 ※全カラム、nullは存在しません。 ※各レコードの格納順に統一性はありません。 ※動作環境はAccess mdb(Office 2007)/Windows7(32bit)です。 【最終的にやりたいこと】 マスタTBLより、最繁日3日分(同じ年月日のレコード数が多い上位3日分)を選定し、 更に時間別、かつコード別の件数を求める(.csv出力)のが最終目標です。 SQL一発でできれば良いのですが、私の力ではそれが組めないため2段階に分け、 第1段階として別の作業用TBLを作成し、まずそこに最繁日3日分を抽出&登録、 第2段階で作業用TBLに対して時間別・コード単位の抽出を行う段取りとしました。 ご質問は、第1段階を満たすSQLについてです。 【ご質問】 上記のテーブルがあるとします。 この中から、最繁日3日分(同じ年月日(時分秒は考慮不要)のレコード数が多い上位3日分)の全レコード(抽出には時分秒も必要)を抽出し、同設定の別テーブルへ登録したい。 と言うのがやりたい事なのですが、抽出するSQLが作れず困っております。 現group by設定をしてしまうと、Countさせて上位日数と件数は判明できますが、その全レコードを羅列させる事ができません。 抽出段階で考慮すべきは日付までなので、group byを考えて時分秒を省いてしまうと、その後秒単位で抽出が必要な第2段階が行えなくなってしまいます。 また時分秒をSELECTに指定してしまうと、group byでも時分秒を加えなくてはいけなくなり、「日付3日分で」が満たされなくなってしまいます。。。 現在、group by有りで作成済みのSQL、および出力結果例は下記の通りで、 全く先に進まなくなってしまいました.... [SQL] 'SQL作成 変数A = "INSERT INTO 登録したいTBL " _ & "SELECT 年,月,日,時,分,秒,コード,COUNT(*) AS CNT " _ & "FROM マスタTBL " _ & "group by 年,月,日,時,分,秒,コード " _ & "order by 年,月,日,時,分,秒,コード;" 'SQL実行 Call db.Execute(変数A) [実行結果例] ■テーブル:登録したいTBL | 年 | 月 | 日 | 時 | 分 | 秒 | コード | カウント | +---- +-- +-- +- -+- -+-- +----- +-------+ | 2013 | 10 | 31 | 10 | 05 | 20 | A1234 | 2 | | 2013 | 10 | 31 | 10 | 10 | 00 | B1234 | 2 | | 2013 | 11 | 01 | 00 | 00 | 01 | A1234 | 3 | | 2013 | 11 | 22 | 05 | 10 | 09 | C1234 | 1 | 現状では当然の出力結果ですが、本来出力したいのは、カウントが3件の3レコードと、 2件のレコード*2つ、合計7レコードを出力させたいと言う意味です。 (カウントは必要かと思ったので入れているだけで、仕様上は別に無くても良い物です。) また、とりあえずですが上記SQLが正しく実行され登録したいTBLへ格納される事は確認済みです。 やり方がそもそも間違えている可能性もございますので、その点も含めご指摘ございましたらお願い致します。 以上です。 ご提示できる条件が少なく申し訳ございませんが、ご回答頂ける方がいましたら、 ご教授をよろしくお願い致します。

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

  • ベストアンサー
  • nicotinism
  • ベストアンサー率70% (1019/1452)
回答No.2

こういうことですか? オリジナルテーブル名を、T1 としています。 SELECT TOP 3 年, 月, 日, コード, count(*) AS cnt FROM T1 GROUP BY 年, 月, 日, コード ORDER BY count(*) DESC; で上位3位まで取り出します。 ただし、『同値のcount(*) AS cnt が多い場合』は 3件よりも多くなります。 このクエリを Q1 として、 SELECT T1.年, T1.月, T1.日, T1.時, T1.分, T1.秒, T1.[コード], Q1.cnt FROM T1 INNER JOIN Q1 ON (T1.[コード] = Q1.[コード]) AND (T1.日 = Q1.日) AND (T1.月 = Q1.月) AND (T1.年 = Q1.年); としてみると? 一つにまとめると T1_out テーブルが、年、月、日、時、分、秒、コード、cnt フィールドで用意されていたら INSERT INTO T1_out SELECT [T1].年 AS 年, [T1].月 AS 月, [T1].日 AS 日, [T1].時 AS 時, [T1].分 AS 分, [T1].秒 AS 秒, [T1].[コード] AS コード, QX.cnt AS cnt FROM T1 INNER JOIN (SELECT TOP 3 年, 月, 日, [コード], count(*) AS cnt FROM T1 GROUP BY 年, 月, 日, [コード] ORDER BY count(*) DESC) AS QX ON ([T1].[コード]=QX.[コード]) AND ([T1].日=QX.日) AND ([T1].月=QX.月) AND ([T1].年=QX.年); かな? テスト環境でお試しを。

san1126
質問者

お礼

ご回答ありがとうございました。 もう半年も前にご丁寧なご回答を頂いたにも関わらず、諸事情によりお礼ができずに申し訳ございませんでした。

その他の回答 (1)

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.1

サブクエリ+Topキーワードでどうでしょう? 試験環境が手元にないので、まずはSelectのみ行って試験してください。 select 年, 月, 日, 時, 分, 秒, コード, count(*) カウント FROM マスタTBL where (年 & 月 & 日) in (  select top 3 年 & 月 & 日 年月日, count(*) カウント  FROM マスタTBL  gropu by 年月日  order by カウント desc ) group by 年, 月, 日, 時, 分, 秒, コード order by 年, 月, 日, 時, 分, 秒, コード ;

関連するQ&A

  • ORACLE のSQL について

    おはようございます。 ORACLEのSQLについて教えてください。 GROUP BY で抽出されたデータの レコード数を把握するSQLはどのようにすればよいのでようか。 ********************** 例: SQL: SELECT TEST_CD FROM TABLE GROUP BY TEST_CD 結果: 01 02 03 04 05 ********************** この結果のレコード(5レコード)のSQL式はどのようになりますか?

  • 絞込みする時のSQLの書き方

    お世話になります。 絞込みする時のSQLの書き方について教えてください。 具体的には テーブル名tbl01,フィールド名f01,f02とした場合 1.f01もしくはf02にAという文字を含むレコードを抽出。 SQL = "select * from tbl01 where f01 like '%A%' or f02 like '%A%'" 2.続いて、1で抽出したデータからf01もしくはf02にBという文字を含むレコードを抽出するSQL文 SQL = ????? あくまでも、1と2を満たす条件を1つのSQL文で表す方法です。一旦、1の結果をワークテーブルに落とし、そこから2だけのSQL文を実行するわけではありません。

  • シンプルなSQLの書き方がわかりません。

    以下のSQLをシンプルに一つにしたいのですが、どのように書いたらよろしいでしょうか? どうぞご返答頂けますようお願い申し上げます。 --test1_tblの抽出 select a1 as a1, b1 as b1 from a_tbl where c=1 --test2_tblの抽出 select a1 as a1, e1 as e1 from b_tbl where rowid in (select min(rowid) from ee group by a1) and a1 is not null and a1 !=' ' order by a1 --test1_tblとtest2tblの結合 select t0.a1 as a1, t0.b1 as b1, t1.e1 as e1 FROM test1_tbl t0, test2_tbl t1 WHERE (t0.a1 = t1.a1)

  • SQLでGROUP項目を列表示する方法?

    SQLでGROUP後の結果を列で効率よく取得する方法を教えてください。(Oracle8.1.7) 現状は下記SQLで列表示していますが、あまり良い方法ではないと思います。別の取得方法があれば教えてください。 ○出力したい結果 担当CD1 4月金額 5月金額 担当CD2 4月金額 5月金額 ○現状SQL問題点 ・一応取得可能ですがこれだと月数分毎回GROUPするので時間が勿体無いと思います。 ・T1で4月~5月を範囲でGROUP後、その結果を4月分、5月分と抽出だけしたいのですが可能でしょうか? ・もっと他に効率よい取得方法があれば教えてください。 ○現状のSQL内容 (SELECT A.TANTOCD, T1.KIN1 KINGAKU1, T2.KIN2 KINGAKU2 FROM (SELECT YYMM,TANTOCD FROM TBL WHERE YYMM >= 200204 AND YYMM <= 200205 GROUP BY YYMM,TANTOCD ) A, (SELECT YYMM,TANTOCD,SUM(KIN) KIN1 FROM TBL WHERE YYMM ='200204' GROUP BY YYMM,TANTOCD) T1, (SELECT YYMM,TANTOCD,SUM(KIN) KIN2 FROM TBL WHERE YYMM ='200205' GROUP BY YYMM,TANTOCD) T2 WHERE A.TANTOCD = T1.TANTOCD(+) AND A.TANTOCD = T2.TANTOCD(+));

  • ACCESSのモジュールで

    おはようございます。 Access97で受注管理データベースを作成しています。 新規顧客コード作成の際、いくつかの条件でコードを分けています。 そのためSQLで抽出し、それに1を足して新規コードとしています。 たとえば下記のSQL文を書き、 mySQL="SELECT Max(顧客コード) AS 顧客コードの最大 FROM 顧客マスタ GROUP BY グループ HAVING (グループ='CB');" その抽出結果を取得したいのですが、そのためにはレコードセットとみなさせるのかと思い、いろいろやってみたのですが、結局出来ません。(それからして怪しい) VBAお勉強中で根本的に仕組みを理解できていないせいだと思うんですが、 数冊参考書を見ても分かりませんでした。 分かりにくい質問文ですみません。どなたか助けてください。よろしくお願いします。

  • 重複するレコードを調べるSQL

    重複するレコードを調べるSQL 初歩的な質問ですみません! 重複するレコードを調べるために以下のようなSQLを作ったのですが、 遅くて困っています。 もっと速くする方法があれば教えてください! 異なるカテゴリーでも商品コードが重複しているものがないかを探すSQLです。 SELECT A.商品コード, A.X, B.カテゴリー FROM (SELECT COUNT(商品コード) X, 商品コード FROM テーブルA WHERE 追加年月 = 201008 GROUP BY 商品コード) A, (SELECT 商品コード, カテゴリー FROM テーブルA WHERE 追加年月 = 201008 ) B " WHERE A.X >= 2 AND B.商品コード = A.商品コード

  • ACCESS2000 SQL 最大レコード数

    こんにちは。 [TBL] キーは A B DD Cです。 A B DD C E 1 2 21 7 ..... 1 2 21 8 ..... 1 2 22 3 ..... 1 2 22 8 ..... 1 2 22 9 ..... 3 1 2 1 ..... 3 3 4 2 ..... から、A=1 B=2の数の最大レコード数をカウントしたいです。 但し、DDは同じ数なことが条件です。 上でいうと、D=22のものが3つあり、D=21のものが2つあるので、最大は3ということで、3を取得したいです。 select count(*) FROM TBL where A=1 AND B=2 GROUP BY C に近い感じだとはおもうのですが。 よろしくお願い致します。

  • SQL文のロジックについて

    SQLの初心者ですので具体的な例でお答えいただければうれしいです a  char(13)   の中に ’099-222-5678 ’ と入ってるとします ’-’の場所は不定です aの値を、’099’、’222’、’5678’に分けるときは どのように記述したら良いのですか? もうひとつ・・・ AというファイルのKEYが、社員コード、連番で内容が名前 社員コード、連番、名前 とあるとして 1社員コードに対して連番が10件存在する・・・として 名前は連番に対してあると思います そこで、名前がSPACEでかつ連番が一番小さいデータを一件 だけ抽出するにはどんなWHEREかけばよろしいのですか? よろしくお願いします

  • ACCESSとORACLEで抽出結果が異なる

    いつもお世話になっております。 ACCESS2000を扱っております。 ACCESSのデータベースにODBCを接続してORACLEの テーブルをリンクテーブルとしてインポートします。 そして、ACCESSのテーブルとORACLEのテーブルを LEFT JOIN を行いクエリーを作成したのですが、 正しい結果が抽出できません。 ただし、ORACLEのテーブル構成・データと全く同一の ACCESSのテーブルを作成し、クエリーを作成したところ 正常に動作しております。 SQLは以下のような内容となっております。 sSQL = SELECT TBL_1.A, TBL_1.B, TBL_1.C FROM TBL_1 LEFT JOIN TBL_2 ON TBL_1.A = TBL_2.A AND TBL_1.B = TBL_2.B AND TBL_1.C = TBL_2.C WHERE TBL_2.A IS NULL AND TBL_2.B IS NULL AND TBL_2.C IS NULL TBL_1がORACLEより引っ張ってきたリンクテーブル、 TBL_2がACCESSに存在するテーブルになります。 以上のSQLで、TBL_2に存在なくTBL_1に存在するレコード、及びTBL_1とTBL_2でキー項目は同じだが 内容が異なるレコードを抽出できると考えているのですが、TBL_2に存在なくTBL_1に存在するレコードしか 抽出できません。 個人的には、処理する件数が多大であることが影響しているのかとも考えているのですが・・・。 (両テーブルともに約20万件レコード) クエリーを分割することで解決はしたのですが、 原因究明を求められておりまして大変困っています。 皆様の知恵を借りたいです。宜しくお願いいたします。

  • SQL文について

    OracleやSQLについてはまだ初心者のレベルで理解が浅いので言葉足らずかもしれませんがよろしくお願いします。 以下のようなテーブル(名称:TBL)があったとします。 SHOP_CODE------SHOP_NUMBER----MONEY1------MONEY2 A ---------------- 1 ---------------- 100 ------------- 200 B ---------------- 2 ---------------- 300 ------------- 400 C ---------------- 3 ---------------- 500 ------------- 600 D ---------------- 4 ---------------- 700 ------------- 800 例えば、SHOP_CODEがA~Dのどれかの行(レコード)はそのまま抽出して、残った行(レコード)はMONEY1およびMONEY2を0に変更して抽出しようとした場合、 SELECT * FROM TBL WHERE SHOP_CODE = 'ここはA~Dのどれかを代入' UNION SELECT SHOP_CODE, SHOP_NUMBER, 0, 0 FROM TBL WHERE SHOP_CODE <> 'A~Dのどれかを代入' このようなSQL文を考えてみました。 しかし、比較的簡単な例ならばよいのですが、UNION前のSELECT文が複雑になってきた場合のことを考え以下のような文の作りかたができないかと思いました。 SELECT * FROM TBL WHERE SHOP_CODE = 'ここはA~Dのどれかを代入'・・・『この時点で抽出した塊になんらかの名称をつける(例:tbl)』 UNION SELECT SHOP_CODE, SHOP_NUMBER, 0, 0 FROM TBL WHERE SHOP_CODE <> tbl.SHOP_CODE・・・『このようにUNION以前に抽出した塊の名称を利用して条件を作成』 このような方法ができるとした場合、前段階で抽出した塊にどのような方法で名称をつけるのか分かりませんでした。(汗)そもそもできるかどうかもわかりませんが、、、(^^; 最初のSQL文がベターな方法なのかも分かりませんが、上記に示した方法で抽出することが可能でしょうか?もしできるのならば、前述したように名称をつけて条件を作成する方法等を教えていただきたいと思います。 おおよそ話を分かっていただければよいのですが、ものすごく簡単に言うと一つのテーブルのある行とある行に別々の処理をして再構成したいというようなイメージです。(今回はMONEYを0にすると仮定しました) できれば上記の方法に沿った考えで回答をいただけると私も助かりますが、もっと良い方法があれば是非伺いたいと思います。お時間の方ありましたらよろしくお願いします。

専門家に質問してみよう