Microsoft Access 掲示板

サブクエリの書き方について

7 コメント
views
4 フォロー

サブクエリについて教えてください。お願いします。

経営する店舗の集計に関する事です。
添付図のように、集計がしたいのです。

集計する条件

伝票IDが同じ
テーブル番号が同じ
日時が同じ
合計が14,440円

本指名者で14,440円の売上を等分する。

Q_売上合計

SELECT MT_売上.伝票ID, MT_売上.[テーブル番号], MT_売上.日時, Sum(MT_売上.[ドリンク代金]) AS ドリンク代金の合計
FROM MT_売上
GROUP BY MT_売上.伝票ID, MT_売上.[テーブル番号], MT_売上.日時;

Q_本指名カウント


SELECT Q_本指名カウント.伝票ID, Q_本指名カウント.[テーブル番号], Q_本指名カウント.日時, Count(Q_本指名カウント.指名) AS 指名のカウント
FROM Q_本指名カウント
GROUP BY Q_本指名カウント.伝票ID, Q_本指名カウント.[テーブル番号], Q_本指名カウント.日時;


Q_集計本指名カウント

SELECT Q_本指名カウント.伝票ID, Q_本指名カウント.[テーブル番号], Q_本指名カウント.日時, Count(Q_本指名カウント.指名) AS 指名のカウント
FROM Q_本指名カウント
GROUP BY Q_本指名カウント.伝票ID, Q_本指名カウント.[テーブル番号], Q_本指名カウント.日時;

Q_バック代金


SELECT Q_売上合計.伝票ID, Q_売上合計.[テーブル番号], Q_売上合計.日時, Q_売上合計.[ドリンク代金の合計], ([ドリンク代金の合計])/([指名のカウント]) AS バック, MT_売上.名前, MT_売上.指名
FROM (Q_売上合計 INNER JOIN Q_集計本指名カウント ON (Q_売上合計.日時 = Q_集計本指名カウント.日時) AND (Q_売上合計.[テーブル番号] = Q_集計本指名カウント.[テーブル番号]) AND (Q_売上合計.伝票ID = Q_集計本指名カウント.伝票ID)) INNER JOIN MT_売上 ON (Q_売上合計.日時 = MT_売上.日時) AND (Q_売上合計.[テーブル番号] = MT_売上.[テーブル番号]) AND (Q_売上合計.伝票ID = MT_売上.伝票ID)
WHERE (((MT_売上.指名)="本指名"));


Q_Caset売上

SELECT MT_売上.伝票ID, MT_売上.[テーブル番号], MT_売上.日時, MT_売上.指名, MT_売上.名前, MT_売上.[ドリンク], MT_売上.[ドリンク代金], Q_バック代金.[バック]
FROM MT_売上 LEFT JOIN Q_バック代金 ON (MT_売上.伝票ID = Q_バック代金.伝票ID) AND (MT_売上.[テーブル番号] = Q_バック代金.[テーブル番号]) AND (MT_売上.日時 = Q_バック代金.日時) AND (MT_売上.名前 = Q_バック代金.名前);


Q_Caset売上を作成するまでに、かなりにクエリを書いています。
このクエリを一発で表示するためには、サブクエリを利用するということがわかったのですが、どうしてもできません。

申し訳ありませんが、教えていただけないでしょうか?

画像1

えいじ
作成: 2022/05/08 (日) 22:20:25
通報 ...
1
hiroton 2022/05/09 (月) 09:38:04 修正 41ab0@f966d

質問内の「Q_本指名カウント」が間違っている(コピペミス?)のでどこをどうすればとは言えませんが、基本的に後のクエリで呼び出している部分をそっくりそのまま置き換えればうまくいくと思います。置き換えた部分はSQL終了文字(;)を削除して、括弧(())で括ります

ex)
LEFT JOIN Q_バック代金 ON

LEFT JOIN (SELECT Q_売上合計.伝票ID,~(略)~) ON

また、自己結合をする場合、適宜エイリアスを使用し、その他、(サブクエリ関係なく)一般的なクエリの記述として、複雑なクエリになる場合には適切な括弧の運用が必要になります
具体的にはINNER JOINを連続させる場合、1回であれば必要のない括弧が必要になったりします。

あと、単純に必要な計算の見極めが必要ですね

SELECT
  T1.伝票ID
  ,T1.テーブル番号
  ,T1.日時
  ,T1.指名
  ,T1.名前
  ,T1.ドリンク
  ,T1.ドリンク代金
  ,IIf(T1.指名 = "本指名", T2.テーブル代金 / T3.本指名カウント) AS バック代金
FROM
  (
    MT_売上 AS T1
    INNER JOIN
      (
        SELECT
          伝票ID
          ,テーブル番号
          ,日時
          ,sum(ドリンク代金) AS テーブル代金
        FROM
          MT_売上
        GROUP BY
          伝票ID
          ,テーブル番号
          ,日時
      ) AS T2
    ON
      T1.伝票ID = T2.伝票ID
      AND T1.テーブル番号 = T2.テーブル番号
      AND T1.日時 = T2.日時
  )
  INNER JOIN
    (
      SELECT
        伝票ID
        ,テーブル番号
        ,日時
        ,count(*) AS 本指名カウント
      FROM
        MT_売上
      WHERE
        指名 = "本指名"
      GROUP BY
        伝票ID
        ,テーブル番号
        ,日時
    ) AS T3
  ON
    T1.伝票ID = T3.伝票ID
    AND T1.テーブル番号 = T3.テーブル番号
    AND T1.日時 = T3.日時
;

MT_売上の構造自体が若干怪しいですが、そちらは無視して回答しています

2
りんご 2022/05/10 (火) 00:35:57 c564b@0e907

Q_売上合計

 サブクエリは苦手なので答えられないけど、あれこれやってみました。Dcountを追加してみるのは?
Dcount("指名", "MT_売上", "指名='本指名' AND 伝票ID=" & [伝票ID] & "AND テーブル番号=" & [テーブル番号] & "AND 日時=#" & [日時] "#") AS 本指名の合計
 以下、手打ちなのでエラーが出たらごめんなさい。

SELECT MT_売上.伝票ID, MT_売上.[テーブル番号], MT_売上.日時, Sum(MT_売上.[ドリンク代金]) AS ドリンク代金の合計,Dcount("指名", "MT_売上", "指名='本指名' AND 伝票ID=" & [伝票ID] & "AND テーブル番号=" & [テーブル番号] & "AND 日時=#" & [日時] "#") AS 本指名の合計
FROM MT_売上
GROUP BY MT_売上.伝票ID, MT_売上.[テーブル番号], MT_売上.日時;

 余談ですが、Hatenaさんのサイトを見ながらあれこれするのも楽しかった。
hatena-chips:更新クエリで定義域集計関数を使わずに集計する
 とりあえず、ほにゃららテーブルを作成してから遊んでみると。

SELECT MT_売上.伝票ID, MT_売上.テーブル番号, MT_売上.日時, 0 AS 本指名の合計, 0 AS ドリンク代金の合計 INTO ほにゃららテーブル
FROM MT_売上
GROUP BY MT_売上.伝票ID, MT_売上.[テーブル番号], MT_売上.日時;

 

3
えいじ 2022/05/10 (火) 08:18:00

hiroton様 りんご様 回答ありがとうございました。

hiroton様 スペルミス申し訳ありませんでした。

https://sys-daddy.com/access_subquery/

上記のサイトを参考にして、自分なりにSQL文を記載したのですが、ダメでした。

再度、質問なのですが、エイリアスとは、T1のことをしめしているのでしょうか?

エイリアスを検索したら、エイリアスは、あだ名みたいなものと記載しているサイトがありました。

例えば下記のクエリです。

SELECT T01部品マスタ.部品登録ID, T01部品マスタ.品名, T00小分類マスタ.小分類名,
 T01部品マスタ.型式, T01価格マスタ.価格
 FROM (T00小分類マスタ INNER JOIN T01部品マスタ ON T00小分類マスタ.小分類ID = T01部品マスタ.小分類ID)
 INNER JOIN T01価格マスタ ON T01部品マスタ.部品登録ID = T01価格マスタ.部品登録ID;

SELECT T2.部品登録ID, T2.品名, T1.小分類名, T2.型式, T3.価格
 FROM (T00小分類マスタ AS T1 INNER JOIN T01部品マスタ AS T2 ON T1.小分類ID = T2.小分類ID)
 INNER JOIN T01価格マスタ AS T3 ON T2.部品登録ID = T3.部品登録ID;

T01部品マスタ.部品登録ID⇒T2.部品登録IDに、なぜ変更できるのでしょうか?

この手のコードを理解するにあたり、お勧めの書籍等があれば、教えていただきたいです。

4
えいじ 2022/05/10 (火) 09:21:26

りんご様
https://hatenachips.blog.fc2.com/blog-entry-350.html

この内容スゴイです。
こんな方法もあるんですね。
ありがとうございました。

5
hiroton 2022/05/10 (火) 09:33:09 dc0f5@f966d

データ ソースの代替名を使用する

フィールドまたは式に代替名を使用する: AS キーワード

T01部品マスタ.部品登録ID⇒T2.部品登録IDに、なぜ変更できるのでしょうか?

SELECT T2.部品登録ID, T2.品名, T1.小分類名, T2.型式, T3.価格
 FROM (T00小分類マスタ AS T1 INNER JOIN T01部品マスタ AS T2 ON T1.小分類ID = T2.小分類ID)
 INNER JOIN T01価格マスタ AS T3 ON T2.部品登録ID = T3.部品登録ID;

変更後のクエリでT01部品マスタ AS T2という指定があるので、このクエリの中では「T2T01部品マスタの代わりとして使える」となります。

7
hiroton 2022/05/11 (水) 08:57:57 f4fc4@f966d >> 5

ちょっと訂正

T2T01部品マスタの代わりとして使える
「この部分のT01部品マスタを参照するときはT2を使う」

「あだ名」と言ってしまうと、T01部品マスタT2も同じモノを指すことになります(両方使えそう)が、エイリアスを指定した場合T01部品マスタは使えなくなり、代わりにT2だけが使えるようになります

6
えいじ 2022/05/10 (火) 11:17:50

ありがとうございました。
勉強になりました。