商品の在庫管理のシステムを作ろうと思っています
仕入明細のテーブルから、仕入数量と金額を月別で集計するクエリを作成 「q在庫表仕入」
売上明細のテーブルから、売上数量を月別で集計するクエリを作成 「q在庫表売上」
上記クエリから、月次移動平均で在庫金額を求めるために下記クエリを作成
SELECT
q在庫表仕入.商品ID,
q在庫表仕入.商品名,
q在庫表仕入.期首数量,
q在庫表仕入.期首金額,
q在庫表仕入.[7月仕入数量],
q在庫表仕入.[7月仕入金額],
q在庫表売上.[7月売上数量],
IIf([7月売上数量] Is Null,Null,(Nz([q在庫表仕入].[期首金額],0)+Nz([7月仕入金額],0))/(Nz([q在庫表仕入].[期首数量],0)+Nz([7月仕入数量],0))*[7月売上数量]) AS 7月払出金額,
[q在庫表仕入]![期首数量]+Nz([q在庫表仕入]![7月仕入数量],0)-Nz([7月売上数量],0) AS 7月数量,
[q在庫表仕入]![期首金額]+Nz([q在庫表仕入]![7月仕入金額],0)-Nz([7月払出金額],0) AS 7月金額
以下8月~6月まで繰り返し
FROM q在庫表仕入 INNER JOIN q在庫表売上 ON q在庫表仕入.商品ID = q在庫表売上.商品ID;
このクエリだと半年分くらいまでは上手く表示されるのですが、1年分で実行しようとすると「クエリが複雑すぎます」とエラーになってしまいます
クエリを二つに分けて作成もしてみましたが、2つ目のクエリで同様に複雑すぎますとエラーになってしまいました
何か改善する方法がありましたら教えてください
元のテーブルの構成は不明なので、推測で回答するしかないですが、
クエリを追加クエリにしていったんテーブルに出力してから、そのテーブルをもとにクエリを作成するとうまくいくかも知れません。場合によってはその方が高速な処理になる場合もあります。
返信ありがとうございます。
テーブル等省略してしまってすみません。
追加クエリにすると前月以前のデータを変更した場合でも上手く動くのでしょうか、
商品マスタに各月の在庫数量と在庫金額を更新クエリで入力させれば良いのかとも思ったのですが
やり方がよく分からず・・
お手数ですが教えてもらえないでしょうか。
よろしくお願いいたします。
t決算日
決算日 2020/6/30
t商品マスタ
blob:https://zawazawa.jp/2d95d575-a70c-49d7-9f0c-52d99b7e4e45
t仕入明細
blob:https://zawazawa.jp/92a252de-14c8-4f2e-b55f-c99094e192fd
t売上明細
blob:https://zawazawa.jp/5606e247-2a8b-40d3-80ed-70c928cee4b7
q仕入明細
SELECT
t仕入明細.仕入日,
t仕入明細.仕入先ID,
t仕入明細.仕入商品ID,
t仕入明細.仕入数量,
t仕入明細.仕入単価,
[仕入数量]*[仕入単価] AS 仕入金額
FROM t仕入明細;
q売上明細
SELECT
t売上明細.売上日,
t売上明細.得意先ID,
t売上明細.売上商品ID,
t売上明細.売上数量,
t売上明細.売上単価,
[売上数量]*[売上単価] AS 売上金額
FROM t売上明細;
以下続き
q在庫表仕入
SELECT
t商品マスタ.商品ID,
t商品マスタ.商品名,
t商品マスタ.期首数量,
t商品マスタ.期首金額,
Sum(IIf([q仕入明細]![仕入日] Between DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-11,0)+1 And DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-10,0),[q仕入明細]![仕入数量])) AS 7月仕入数量,
Sum(IIf([q仕入明細]![仕入日] Between DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-11,0)+1 And DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-10,0),[q仕入明細]![仕入金額])) AS 7月仕入金額,
Sum(IIf([q仕入明細]![仕入日] Between DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-10,0)+1 And DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-9,0),[q仕入明細]![仕入数量])) AS 8月仕入数量,
Sum(IIf([q仕入明細]![仕入日] Between DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-10,0)+1 And DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-9,0),[q仕入明細]![仕入金額])) AS 8月仕入金額,
・・・・・以下繰り返し
FROM t決算日, t商品マスタ INNER JOIN q仕入明細 ON t商品マスタ.商品ID = q仕入明細.仕入商品ID
GROUP BY t商品マスタ.商品ID, t商品マスタ.商品名, t商品マスタ.期首数量, t商品マスタ.期首金額;
q在庫表売上
SELECT
t商品マスタ.商品ID,
t商品マスタ.商品名,
t商品マスタ.期首数量,
t商品マスタ.期首金額,
Sum(IIf([q売上明細]![売上日] Between DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-11,0)+1 And DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-10,0),[q売上明細]![売上数量])) AS 7月売上数量,
Sum(IIf([q売上明細]![売上日] Between DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-10,0)+1 And DateSerial(Year([t決算日]![決算日]),Month([t決算日]![決算日])-9,0),[q売上明細]![売上数量])) AS 8月売上数量,
・・・・・以下繰り返し
FROM t決算日, q売上明細 INNER JOIN t商品マスタ ON q売上明細.売上商品ID = t商品マスタ.商品ID
GROUP BY t商品マスタ.商品ID, t商品マスタ.商品名, t商品マスタ.期首数量, t商品マスタ.期首金額;
画像のアップロードができていなかったので、改めて載せます
元データをうまいことくっつけてから集計は最後にやるのがいいんじゃないかなぁと
ついでに「日付」のままだとごちゃごちゃしてしまうところを、扱いやすいように「月(のようなもの)」に変換しています
期首をマイナス1月の仕入れとみなし、7月から翌6月は0月~11月として計算式が単純になるようにしています
※「月次移動平均」に関係する計算式そのものの是非は見ていません
返信ありがとうございます。
教えていたコードをもとに作成してみましたが、12か月分入力すると
また「クエリが複雑すぎます」と言われてしまいました。
自分で変えた所は、
Sum(IIf([月]=0,[仕入数量])) AS 7月仕入数量,
Sum(IIf([月]=0,[仕入金額])) AS 7月仕入金額,
Sum(IIf([月]=0,[売上数量])) AS 7月売上数量,
([期首金額]+[7月仕入金額])/([期首数量]+[7月仕入数量])*[7月売上数量] AS 7月払出金額,
Sum(IIf([月]<=0,[仕入数量]-[売上数量])) AS 7月数量,
[期首金額]+Nz(Sum(IIf([月]=0,[仕入金額])),0)-Nz([7月払出金額],0) AS 7月金額,
上記、NZを追加したことと
union all
SELECT
仕入商品ID,
"",
iif(Month([仕入日])<7,Month([仕入日])+6,Month([仕入日])-7),
仕入数量,
仕入単価*仕入数量,
0,
0
FROM t仕入明細, t決算日
WHERE 仕入日 Between DateAdd("yyyy",-1,[決算日]+1) And [決算日]
modだと12月以降の数字がマイナスになってしまったので上記のように変えてみました。
自分で直した所で式が複雑になってしまったのでしょうか。
よろしくお願いいたします。
すみません。計算式を間違えていました。
見えてる範囲の(画像の)データを作成し試していますが、NZ追加、月算出方法の変更を掛けてもこちらでは問題なく表示がされます。
ということですが、表示できなくなるのは質問同様半年を超えたあたりということでしょうか?
クエリで表示月を減らすと表示されますか?
新規にACCESSファイルを作り、テストデータを作ってみるとどうですか?
新たにデータベース、テーブルを作成し、レコードを数行入力して下記コードで実行してみましたが
10か月未満では表示できましたが、それを超えると表示できなくなってしまいました。
何か他に原因があるのでしょうか。
現象を確認しました。
hirotonの上げた構文は8月以降の式が想定と異なっていたためエラーにならなかったようです。
いろいろ試してみましたが、一時テーブルを作成して、「n月金額」部分のみ計算させるような(sumもiifもnzもない)クエリを作っても11か月以上同時に表示しようとするとエラーが発生してしまいました。
フィールドを順次参照していることと、そのフィールドが計算式になっていることが重なって「複雑」となるようですが、明確な条件はわかりませんでした。
いろいろやってみたところ、クエリでの計算を減らすとなんとかなることもあるようでした。例えば標準モジュールに以下のユーザー定義関数を作成し、クエリ上の計算式を置き換えます。
ただ、表示までこぎつけても、数件のテストデータだけでも表示までにそれなりの時間がかかっていたので、実用できるかはちょっと疑問です。「複雑すぎ」ると言われるのも納得かなと
金額計算部分がフィールドを繰り返し参照する重い処理になっているので、出力用のテーブルを事前に作成しておいて金額部分以外を出力したのち、VBAで金額部分を計算させるのがいいんじゃないのかなぁと思いました
「月次移動平均」というのを知らなかったのと、hirotonさんの回答が付いたので、お任せしてましたが、なかなか苦労してますね。
「月次移動平均」というものをちょっと調べてみましたか、下記の理解であってますでしょうか。
期首日からのある月までの合計金額を合計数量で割ったもの。
つまり、今回は6/30が決算日のようですので、
7月度移動平均は、(期首金額+7月金額計)/(期首数量+7月数量計)
8月度移動平均は、(期首金額+7月~8月金額計)/(期首数量+7月~8月数量計)
9月度移動平均は、(期首金額+7月~9月金額計)/(期首数量+7月~9月数量計)
・・・
ということでよろしいでしょうか。
ということなら、そのデータベースのファイルを送付してもらえますか。
右カラムの一番下に「ファイル送信フォーム」のリンクがありますので、そこから送信してください。
内容を確認して、ここにファイルリンクを置きますので、だれでもダウンロードしてそれをもとに実験できますので、的確な回答が付きやすいと思います。
ちょっと考えてみました。
まず、下記のようなテーブルを作成します。
テーブル名 T月
月ID に 1 から 12 までの数値を入力します。
下記の更新クエリを実行します。
これでt月は下記のようになります。
下記のようなクエリを作成します。
これで移動平均を計算できるデータは揃うと思いますがいかがでしょうか。
実際のデータでの確認はしてませんので、見落としがあるかもしれません。
考え方を参考にしてください。下記のような考え方です。
上記で仕入関係のデータは得られます。移動平均もクエリ内で計算できると思います。
同様に、売上関係のデータを出力するクエリを作成します。
2つのクエリを[月ID]で結合すれば月別の移動平均データができると思います。
月別データが縦に並びますが、もし、横に並べないなら、クロス集計クエリで横並びに変換できます。
hirotonさん
返信ありがとうございます。
商品数が数百と仕入売上で数千レコードあるのでやはり難しそうですね。
商品別に仕入数量、仕入金額、売上数量をまとめてVBAで金額部分を計算という方法でやってみようと思います。
エクセルでVBAをちょっと触ったくらいの知識しかないので、時間がかかるかもしれませんがまた相談させてください。
hatenaさん
返信ありがとうございます。
月次移動平均は下記の計算方法になります。
・期首在庫数量
・期首在庫金額
・7月仕入数量
・7月仕入金額
・7月払出数量
・7月払出金額 → (期首在庫金額+7月仕入金額)/(期首在庫数量+7月仕入数量)× 7月払出数量
・7月在庫数量 → 期首在庫数量+7月仕入数量-7月払出数量
・7月在庫金額 → 期首在庫金額+7月仕入金額-7月払出金額
毎月の在庫金額が前月の在庫金額を元に計算してしまうので複雑になってしまうという事ですね。
2020/04/08 の私の回答の方法を一度試してみてください。
集計期間の日付を更新クエリで t月 に生成しますので、それを使って集計するようにします。その為に、式はシンプルになります。2つめのクエリで月次移動平均の計算に必要なデータは揃うと思いますので、それに必要な式を追加すればできると思います。
VBAを使う方法ってことでつらつらと
まずは下準備から
データ出力用のテーブルを用意します。
T月次移動平均表
本来出力したかったクエリの全フィールドを持ったテーブルです。データ型は適宜設定してください。
各月の「払出金額」と「金額」は平均の処理が入るから倍精度浮動小数点型になるのかな?
データ処理用のクエリを用意します(2つ)
Q月次移動平均表Clear
ワークテーブルを使いまわすので処理前にまっさらにするようクエリです。
Q月次移動平均基礎データ作成
各月の「払出金額」と「(集計)金額」を除いた基礎となるデータを追加クエリでワークテーブルに追加するクエリです。
メインのVBAコード
変数の型(平均計算で小数点以下がでる)のと
/ (前月数量 + 仕入数量)
があるのでそこの条件判断をしてあげないといけないかなぁという感じ計算部分はちょっと自信ないので出力結果が正しいかは十分にテストしてください
テーブル、クエリ、VBAと使うものが多いのでフィールド名を変えたりする場合はよく見てください
ワークテーブルを使う方法は実行する度にACCESSファイルが肥大化するので適宜、最適化が必要になると思います。大本のデータとはファイルを分けてリンクテーブルで拾うようにするといいかな?
いろいろ手間な部分もあるのでhatenaさんの方法でうまくいけばそれでいいんじゃないかな。とも
すでに解決済みかもしれませんが、最近この症状にはまって一応解決したのでコメントさせて頂きます
解決方法は、Accessを64bitで再インストールしたらエラーがなくなりました、根本的な解決ではないかもしれません
私の場合32bitだったのでもしやと思い64bitにしたというだけです、何らかの上限や制約があるかもしれないのでもしかするともっとクエリを複雑にすると64bitでも同じ症状が出るかもしれません
何かの参考になれば幸いです
原因がはっきりしているエラーなので、根本的に設計からやり直して解決するしかないでしょう。臭い物に蓋をしても遅かれ早かれ損切りするしかないですわー。