Microsoft Access 掲示板

在庫数の算出

29 コメント
views
4 フォロー

ACCESSにて在庫の管理を行いたいと思っております
クエリを用いて当月の前月在庫数、当月入庫数、当月出庫数、当月在庫数を出したいと考えておりますが、
どのように行えばいいのかわかりません。
テーブルは以下のように作成しております。
・出荷先
  出荷先ID(主)
  出荷先名

・出庫
  出庫ID(主)
  出庫日
  出荷先ID

・出庫詳細
  出庫詳細ID(主)
  出庫ID
  製品ID
  出庫数量
  備考

・製品
  製品名(主)
  仕様
  測温範囲
  備考

・入荷先
  入荷先ID(主)
  入荷先名

・入庫
  入庫ID(主)
  入庫日
  入荷先ID

・入庫詳細
  入庫詳細ID(主)
  入庫ID
  製品ID
  入庫数量
  備考

最終的には指定した月までの商品毎の前月在庫数、当月入庫数、当月出庫数、当月在庫数を
レポートに表示できればと考えております。

ご助言の程、よろしくお願いします

フック船長
作成: 2019/12/05 (木) 13:19:57
通報 ...
1
フック船長 2019/12/06 (金) 09:09:58 f3309@31d50

画像1

2
hiroton 2019/12/06 (金) 09:38:56 78df5@f966d

どの程度のことができるのかわからないのでヒントだけ

最終的には横並びに月と入庫数や出庫数を見たいのだと思いますが、出庫と入庫が別々なテーブルに分かれているのでちょっと面倒です。
ユニオンクエリ集計クエリあたりをつかって入出庫集計クエリを作ります

「在庫」は「その月までの入庫の合計-出庫の合計」と計算させるのが基本ですが、レポートを使うのであればテキストボックスのプロパティ「集計実行」を使って簡単に実装できます

3
フック船長 2019/12/06 (金) 15:54:45 f3309@31d50

ご助言ありがとうございます。

私自身、本を見ながらの組んでいたもので基本的には初心者です。
ユニオンクエリと言われてピンときません。
SQL?とかを学習しないと難しいでしょうか?
SQLやユニオンクエリ、集計クエリをどのように行えばいいのかわかりません。
大変申し訳ありません。

4
hiroton 2019/12/06 (金) 18:41:52 78df5@f966d

SQLを学習するために意気込む程の気持ちはなくても大丈夫です。
ACCESSなら「クエリデザインでデザインビューとSQLビューを切り替えて確認できる」くらいに思っておけば大丈夫です。
違いは、デザインビューは画面操作で簡単にSQLが作れるけれど複雑SQLは作れない(ユニオンクエリもこれに該当)といった程度です。

インターネット上でやり取りをする場合はテキストベースがほとんどですので、SQLを文字列で扱えるとなれば大きなアドバンテージになります。
(扱えると言うのはコピー&ペーストができるというレベルで大丈夫です)


それではもっと基本的なところからもう少し具体的な手順を

1.選択クエリで出庫明細、入庫明細を作る

元の元になるデータとして
出庫明細

製品ID出庫日出庫数量


入庫明細

製品ID入庫日入庫数量

といったデータが必要になります。選択クエリで問題なく作れますか?
今後のやり取りを楽にするために、それぞれ出来上がったものはQ出庫明細Q入庫明細(クエリは頭文字にQをつける)としておきましょう

2.ユニオンクエリでデータを縦につなげる(前段階)

それぞれ出来上がったQ出庫明細Q入庫明細を使いやすいように手を入れます。
Q出庫明細

製品ID出庫日出庫数量

製品ID入出庫日入出庫数入出庫フラグ
(すべて"出庫")

Q入庫明細

製品ID入庫日入庫数量

製品ID入出庫日入出庫数入出庫フラグ
(すべて"入庫")

クエリビューではユニオンクエリが作れないので作業を簡単にするためにQ出庫明細Q入庫明細を同じ列数、同じ列名に揃えておきます。
さらに、合体させた後に入庫なのか出庫なのかわかるように[入出庫フラグ]フィールドを追加しておきます(このフィールドのデータはすべて「出庫」または「入庫」で固定)

3.ユニオンクエリで入出庫明細をつくる

Q入出庫明細

製品ID入出庫日入出庫数入出庫フラグ
("入庫"または"出庫")

事前準備をしてあるので、最も基本的なユニオンクエリの使い方でつくれます

4.集計クエリで入出庫数を横に並べる

Q入出庫集計_sub

製品ID入出庫日入庫出庫

これも集計クエリとしては基本的な使い方をやることになります。
まだ月ごとの集計になっていないのでQ入出庫集計_subとしておきます。


とりあえずここまで
どこまでできますか?
躓いたら出来上がったところまでのクエリをSQLビューで表示してこの掲示板にコピペしつつ質問しましょう
(SQLビューを開けばSQL文がすべて反転表示されているはずなのでそのまま右クリックからコピーするだけです)

5
フック船長 2019/12/11 (水) 15:50:58 f3309@31d50

hiroton 様
返信が遅くなり申し訳ございません。
上記4番で躓いてしまいました。

1から3迄は以下のように行いました。

Q入庫 SQL
SELECT 入庫.入庫日 AS 入出庫日, 製品.製品ID, 入庫詳細.入庫数量 AS 入出庫数, "入庫" AS 入出庫区分
FROM (入荷先 INNER JOIN 入庫 ON 入荷先.入荷先ID = 入庫.入荷先ID) INNER JOIN (製品 INNER JOIN 入庫詳細 ON 製品.製品ID = 入庫詳細.製品ID) ON 入庫.入庫ID = 入庫詳細.入庫ID;

Q出庫 SQL
SELECT 出庫.出庫日 AS 入出庫日, 製品.製品ID, 出庫詳細.出庫数量 AS 入出庫数, "出庫" AS 入出庫区分
FROM 製品 INNER JOIN ((出荷先 INNER JOIN 出庫 ON 出荷先.出荷先ID = 出庫.出荷先ID) INNER JOIN 出庫詳細 ON 出庫.出庫ID = 出庫詳細.出庫ID) ON 製品.製品ID = 出庫詳細.製品ID;

SELECT 入庫.入庫日 AS 入出庫日, 製品.製品ID, 入庫詳細.入庫数量 AS 入出庫数, "入庫" AS 入出庫区分
FROM (入荷先 INNER JOIN 入庫 ON 入荷先.入荷先ID = 入庫.入荷先ID) INNER JOIN (製品 INNER JOIN 入庫詳細 ON 製品.製品ID = 入庫詳細.製品ID) ON 入庫.入庫ID = 入庫詳細.入庫ID
UNION ALL SELECT 出庫.出庫日 AS 入出庫日, 製品.製品ID, 出庫詳細.出庫数量 AS 入出庫数, "出庫" AS 入出庫区分
FROM 製品 INNER JOIN ((出荷先 INNER JOIN 出庫 ON 出荷先.出荷先ID = 出庫.出荷先ID) INNER JOIN 出庫詳細 ON 出庫.出庫ID = 出庫詳細.出庫ID) ON 製品.製品ID = 出庫詳細.製品ID;

6
フック船長 2019/12/11 (水) 15:59:36 f3309@31d50

>> 5
誤字脱字がありました。大変申し訳ありません。
Q出庫 SQL→ Q出庫明細 SQL
Q入庫 SQL→ Q入庫明細 SQL
無題      →  Q入出庫明細 SQL
です。

7
フック船長 2019/12/11 (水) 16:13:40 f3309@31d50 >> 6

画像1
画像2

8
フック船長 2019/12/11 (水) 16:25:57 f3309@31d50 >> 6

Q入出庫明細のクロス集計クエリを選択し、行見出しを製品IDと入出庫日をし、列見出しを入出庫区分に選択。値を集計するフィールドを入出庫数にし、集計方法を合計を選択すればよろしいでしょうか?

9
フック船長 2019/12/11 (水) 16:36:50 f3309@31d50

このように行いました。
TRANSFORM Sum(Q入出庫明細.入出庫数) AS 入出庫数のカウント
SELECT Q入出庫明細.製品ID, Q入出庫明細.入出庫日
FROM Q入出庫明細
GROUP BY Q入出庫明細.製品ID, Q入出庫明細.入出庫日
PIVOT Q入出庫明細.入出庫区分;

画像1
画像2

10
hiroton 2019/12/11 (水) 18:52:32 5e144@f966d

(おわび:回答で、クロス集計クエリとすべきところを集計クエリとしていました。わかりにくかったと思います。無事に進んでいるようで何よりです)


大元になる明細ができたら月ごとの集計を作ります。
入出庫日を各月になるように変換する必要がありますが、クエリでは「入出庫区分」を作ったように、計算結果をデータとするフィールドを出力することができます。

Q入出庫明細のクロス集計クエリを元に新しくクエリを作り製品ID,出庫,入庫フィールドと、「年月: format([入出庫日],"yyyymm")」フィールドを作成します。
このクエリ(選択クエリ)で集計機能を使い、製品IDと年月でグループ化、出庫と入庫を合計すれば各製品IDの月ごとの出庫と入庫が出来上がります。

SELECT 製品ID, Sum(出庫) AS 出庫の合計, Sum(入庫) AS 入庫の合計, Format([入出庫日],"yyyymm") AS 年月
FROM Q入出庫明細のクロス集計クエリ
GROUP BY 製品ID, Format([入出庫日],"yyyymm");

後は、このクエリを基にレポートを作成すれば、>> 2の通り製品IDごとに各月の在庫まで表示できるでしょう。

指定した月まで
レポートに表示できれば

どのような方法を考えているのか、レポートをどの程度扱えるのかわからないので今回もここまで


Format([入出庫日],"yyyymm")の解説
今回、月ごとの集計を出したということで、日付データから月データを作ります。
日付から月を取り出す関数としてはmonth([日付])がありますが、データベースが運用されれば年も跨ぐでしょう。2019年の11月の数字と2020年のそれが合算されたらまずいでしょうから、「年」の情報も含んだ「年月」フィールドにします。

format関数そのものについては調べてみてください。
今回は、例えば「2019/12/01」という日付のデータを「201912」のように変換する使い方になっています。



余談
いまさらですが、テーブル構造が先に出ていたのでユニオンクエリを使って~と進めましたが、入出庫ぐらいなら最初から一つのテーブルでいいんじゃないかと思います。
(最初から入出庫区分を付けたテーブルで管理し、必要に応じて入出庫区分='出庫'等のクエリを発行する)
そのほかのテーブルについても入庫・出庫で分かれていますが、内容は同じものになるのでしょう。
これらについてはむしろ、入庫であるか、出庫であるかという区分も必要ないように見えるのでデータを分けてしまうのは良くないでしょう。

11
hiroton 2019/12/23 (月) 15:33:29 fbc4e@f966d

その後いかがでしょうか。
レポートで「集計実行」を使うと簡単だと言いましたが、実はこの方法には問題点があります。

レポートに表示できれば

とのことだったのでとりあえず形にしてから再修正を、と思っていましたが、(自分の方法のままでは)形にならなさそうな気がしてきたので追記を入れておきます。(ホントはQA形式で進めていきたかったのですが)

まず、レポートの表示を次のように考えることとします。

2019年12月

製品名前月在庫入庫出庫当月末在庫
AAA10010015050
BBB0502030

次に、レポートに表示する月はフォーム上で入力することとします。
・フォーム名:フォーム1
・フォーム1上のテキストボックス:表示月
表示月には表示したい月の1日を入力することとします。(2019年12月のレポートを表示したい場合は2019/12/1)

当月入出庫のデータ、当月在庫用のデータを作る

Q入出庫明細のクロス集計クエリを元に次のクエリを作成します。
Q当月入出庫

PARAMETERS [Forms]![フォーム1]![表示月] DateTime;
SELECT 製品ID, Sum(出庫) AS 当月出庫, Sum(入庫) AS 当月入庫
FROM Q入出庫明細のクロス集計クエリ
WHERE 入出庫日 Between DateSerial(Year([Forms]![フォーム1]![表示月]),Month([Forms]![フォーム1]![表示月]),1) And DateSerial(Year([Forms]![フォーム1]![表示月]),Month([Forms]![フォーム1]![表示月])+1,1)-1
GROUP BY 製品ID;

Q当月まで入出庫

PARAMETERS [Forms]![フォーム1]![表示月] DateTime;
SELECT Q入出庫明細のクロス集計クエリ.製品ID, Sum(出庫) AS 出庫の合計, Sum(入庫) AS 入庫の合計, 製品.製品名
FROM Q入出庫明細のクロス集計クエリ LEFT JOIN 製品 ON Q入出庫明細のクロス集計クエリ.製品ID = 製品.製品ID
WHERE 入出庫日<=DateSerial(Year([Forms]![フォーム1]![表示月]),Month([Forms]![フォーム1]![表示月])+1,1)-1
GROUP BY Q入出庫明細のクロス集計クエリ.製品ID, 製品.製品名;

それぞれ必要に応じた日付の範囲(where条件)で出庫、入庫を合計します。
具体的にはフォーム1の表示月に「2019/12/1」と入っていれば
上は「Between #2019/12/1# And #2019/12/31#」、
下は「<= #2019/12/31#
となるような条件になっています。
Q当月まで入出庫では必要に応じて製品の情報を加えておきます。

クロス集計クエリを使う場合、フォーム上の値を使うためにはパラメーターの設定が必要です。
SQLビューであれば一番上に入っている1行ですが、デザインビューであればデザインビュー上側の適当な位置で右クリックして表示されるポップアップメニューから「パラメーター」を選択して設定できます。

レポート用のソースを作る

上の2つのクエリを基にさらにクエリを発行します。

SELECT Q当月まで入出庫.製品名, Nz([在庫],0)-Nz([当月入庫],0)+Nz([当月出庫],0) AS 前月在庫, Nz([当月入庫],0) AS 入庫, Nz([当月出庫],0) AS 出庫, Nz([入庫の合計],0)-Nz([出庫の合計],0) AS 当月末在庫
FROM Q当月まで入出庫 LEFT JOIN Q当月入出庫 ON Q当月まで入出庫.製品ID = Q当月入出庫.製品ID;

ところどころにあるNz関数データがなかった時に別な値に置き換える関数です。
データがなかった時の値はNullになりますがNullが含まれた計算は結果がNullになるという特性がありますので、例えば12月の出庫がない製品の在庫を計算しようと在庫+入庫+出庫(Null)を単純にしてしまうと計算結果がNull(画面上では表示なし)になってしまいます。

このクエリを表示すれば、上に挙げたレポートの表示形式のデータが表示されますので、このクエリを基にレポートを作成すれば完成です。

12
フック船長 2019/12/23 (月) 17:06:01 f3309@31d50

連絡が遅くなり申し訳ございません。
何とかできるかと軽い気持ちで考えてみましたら思ったようなものができず、どうしたものかと悩んでおり遠のいておりました。
回答していただいたものでやってみます。
少々、お時間をくだされば幸いです。

13
フック船長 2019/12/23 (月) 17:43:59 f3309@31d50

写真が横になって申し訳ありませんがこのようなものができればと考えていました。<a

14
フック船長 2019/12/24 (火) 08:46:50 f3309@31d50

画像1
画像2

15
hiroton 2019/12/24 (火) 10:19:10 4dc36@f966d

いくつか書式の違うレポートを作りたいということですね。
表示に差異はあっても元にするデータは同じなのでユニオンクエリ→クロス集計クエリの流れは基本的なデータの整形としてよくとる手です。
(最初から入出庫テーブルにしてしまえばユニオンクエリをやらなくていい分楽できますが)

2枚目の画像(月別在庫表)については新たに提示した手順のほうでうまくできると思います。

1枚目の画像(商品毎入出庫履歴)はちょっと複雑で、集計と明細が含まれた形なのでサブレポートを組み込むのが楽な方法かと思います。
(改ページを考えたときに先頭行をどうするか等で変わってくると思います)
前月末在庫は最後のクエリで計算されていますので、これを基にレポートを作成して、製品IDでグループ化、改ページの設定をすれば製品ごとのページが出来上がります。
明細部分はQ入出庫明細のクロス集計クエリから日付を条件にデータを抽出したデータをサブレポートにして製品IDでリンクして表示させるという形です。
最後の「合計」は吹き出しの説明がコピペになっていませんか?ちょっとよくわかりませんが見た目からすると「当月出庫数の合計」ですかね?レポートで合計する方法もまずは調べてみてください。

16
フック船長 2019/12/26 (木) 10:30:44 f3309@31d50

すいません。
いただいたレポート用ソースのSQLですが[在庫]を有効なフィールドまたは式として認識できませんと表記されてしまいました。

SELECT Q当月まで入出庫.製品名, Nz([在庫],0)-Nz([当月入庫],0)+Nz([当月出庫],0) AS 前月在庫, Nz([当月入庫],0) AS 入庫, Nz([当月出庫],0) AS 出庫, Nz([入庫の合計],0)-Nz([出庫の合計],0) AS 当月末在庫
FROM Q当月まで入出庫 LEFT JOIN Q当月入出庫 ON Q当月まで入出庫.製品ID = Q当月入出庫.製品ID;

この[在庫]というのはQ当月まで入出庫、Q当月入出庫には入っていないものだと思うのですが…

17
hiroton 2019/12/26 (木) 21:10:04 04d88@f966d

あぁ、すみません
回答前に少し修正を入れたらミスってました

SELECT 製品名, Nz([当月末在庫],0)-Nz([当月入庫],0)+Nz([当月出庫],0) AS 前月在庫, Nz([当月入庫],0) AS 入庫, Nz([当月出庫],0) AS 出庫, Nz([入庫の合計],0)-Nz([出庫の合計],0) AS 当月末在庫
FROM Q当月まで入出庫 LEFT JOIN Q当月入出庫 ON Q当月まで入出庫.製品ID = Q当月入出庫.製品ID;

「在庫」ではなく「当月末在庫」でした
基にしたクエリから持ってきているフィールドではなく、クエリで作ったフィールドをさらに同じクエリで参照しています
当月の在庫と当月の入出庫から逆算して前月の在庫を出しているという計算です

ちなみに一番最初のフィールドをQ当月まで入出庫.製品IDにするか製品名にするか迷った挙句中途半端な形になってましたのでそこも修正してあります
(レポートのレコードソースにするつもりだったので「製品名」でいいかと思いますが、さらに情報を追加したいとなったときのために製品IDも入れておいたほうがやりやすいかなぁとも思ってます)

18
フック船長 2019/12/27 (金) 10:29:23 f3309@31d50

hiroton様
ご回答ありがとうございます。
確認してみます。

20
フック船長 2019/12/27 (金) 11:41:19 f3309@31d50

hiroton様
確認取れました。ありがとうございました。

21
フック船長 2020/01/09 (木) 18:14:06 f3309@31d50 >> 20

明けましておめでとうございます。

上記のクエリを基にレポートをウィザードで作成しようとしますとクエリのフィールド名が表示しません。どのように行えばレポートを作成できるのでしょうか?

23

>> 1のテーブル構成では、出庫詳細 と 入庫詳細 のフィールド名が、共に「 数量 」なのに
>> 5のSQL文では、出庫詳細 と 入庫詳細 のフィールド名が「 入庫数量 」及び「 出庫数量
また、製品テーブルの 製品型番 というフィールドは 投稿文に掲載されておらず、実際の有無が不明。

こういった情報の欠落や矛盾は、ご自身で修正いただくとして
ご希望の結果は 以下のような SQL で表現できるでしょう。

PARAMETERS [Forms]![フォーム1]![表示月] DATETIME ;
SELECT Format$( Nz( [Forms]![フォーム1]![表示月], Date() ), 'yyyy\年m\月' ) As 年月
     , x.製品ID
     , x.製品型番
     , x.製品名
     , Sum(
           IIf( y.入出庫日 
                  < DateSerial( Year( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) )
                              , Month( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) )
                              , 1 )
              , y.入出庫数 * y.入出庫区分
              , 0
           )
       ) As 前月在庫
     , Sum(
           IIf( y.入出庫日 
                    >= DateSerial( Year( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) )
                                 , Month( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) )
                                 , 1 )
                    And
                y.入出庫区分 > 0
              , y.入出庫数
              , 0
           )
       ) As 入庫
     , Sum(
           IIf( y.入出庫日 
                    >= DateSerial( Year( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) )
                                 , Month( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) )
                                 , 1 )
                    And
                y.入出庫区分 < 0
              , y.入出庫数
              , 0
           )
       ) As 出庫
     , Sum( y.入出庫数 * y.入出庫区分 ) As 当月末在庫
FROM 製品 x
INNER JOIN
(
    SELECT 入庫詳細.製品ID
         , 入庫.入庫日        As 入出庫日
         , 入庫詳細.入庫数量  As 入出庫数
         , 1                  As 入出庫区分
    FROM 入庫
    INNER JOIN 入庫詳細
            ON 入庫.入庫ID = 入庫詳細.入庫ID
    WHERE 入庫.入庫日 
              <= DateSerial( Year( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) )
                           , Month( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) ) + 1
                           , 0 )
    UNION ALL 
    
    SELECT 出庫詳細.製品ID
         , 出庫.出庫日
         , 出庫詳細.出庫数量
         , -1
    FROM 出庫
    INNER JOIN 出庫詳細
            ON 出庫.出庫ID = 出庫詳細.出庫ID
    WHERE 出庫.出庫日
              <= DateSerial( Year( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) )
                           , Month( CDate( Nz( [Forms]![フォーム1]![表示月], Date() ) ) ) + 1
                           , 0 )
) y
ON x.製品ID = y.製品ID
GROUP BY x.製品ID
       , x.製品型番
       , x.製品名
ORDER BY x.製品ID ;

 
中間クエリを作らず、SQLを一筆書きで記述してますので
内容について少し解説しておきます。ポイントは3つ。

【 1 】
FROM句のサブクエリになっているユニオンクエリでは
製品・入荷先・出荷先 各テーブルの列は不要ですから、内部結合を必要最小限に留め、
抽出条件は、最初に評価されるクエリ( 一番内側 )に設定することで 処理を高速化できます。

【 2 】
SELECT句では IIF関数を使って条件分岐させることで
当月在庫と前月在庫を一度に計算します。
( 入庫・出庫に関しても同様 )
こうすると、クロス集計クエリを作る必要もなく、構造を単純化できます。

【 3 】
指定月のパラメータは
フォームのコントロールによる 日付の入力 を想定していますけど
入力をスキップすると、自動的に現在の月が設定されます。

22

クロス集計クエリを使ったクエリを基にするとそうなるようです
クロス集計クエリ(Q入出庫明細のクロス集計クエリ)にクエリ列見出しを設定しておくとレポートウィザードでもフィールド名が表示されるようになります

24
フック船長 2020/01/27 (月) 16:55:39 f3309@31d50

mayu様
返信が遅くなり申し訳ありません。レポートを作成できました。ありがとうございます。

質問ですが作成していただいたSQL文にx.~やy.~と記載されていますがどのような意味があるのでしょうか。(IIF関数に必要な条件のようなものでしょうか)

見当違いで意味がないのであれば申し訳ありません。

25

質問ですが作成していただいたSQL文にx.~やy.~と記載されていますが
どのような意味があるのでしょうか。
(IIF関数に必要な条件のようなものでしょうか)

xy は、 エイリアス と言って
SQL文の中で、一時的に テーブルやクエリに 別の名前をつけています。

 x ---> 製品 ( 実在のテーブル )のこと
 y ---> ユニオンクエリ ( SELECT 入庫詳細.製品ID ... DateSerial( ... , 0 ) ) のこと

私がエイリアスを付与する理由は、主に以下のようなものになります。

【 1 】
SELECT 句や WHERE 句 など、各句の中で
列の名前を エイリアスで修飾( エイリアス名.列の名前 )すると
どのテーブルの列を 射影や選択といった操作の対象としているのか、明確になります。

【 2 】
画数の多いテーブルやクエリに 画数の少ないエイリアス を付与すると
オブジェクト修飾する記述を用いた際に
タイピングが楽(?)で、SQL の見映えがすっきりするという利点があります。( 多分 )

【 3 】
SQL 文中で使用するテーブルやクエリの名前に 予約語や記号などが含まれていて
Microsoft が推奨していない 命名規則 になっている場合、
( 例えば T-table とか T名前(hoge) とか currency とか )
オブジェクト修飾の際に [] で括る記述を強要されて 非常に見映えが悪いため、
( [T-table].列名 とか [T名前(hoge)].列名 とか [currency].列名 とか )
せめて SQL文の中だけでも、まともな命名規則のオブジェクト名を付与したい

【 4 】
複数のオブジェクトに共通して存在する名前の列 を操作する場合だけは
 オブジェクト名.列名
というように、
どのオブジェクトを操作するのか、明確に指定する必要がありますが
( 今回の場合だと 製品ID が該当し、オブジェクト修飾しないとエラーになります )
列によって、修飾したり しなかったりという記述にしてしまうと
長文 SQL の場合は、可読性が落ちますし、一貫性も欠如してしまいます。

 
ですから、単一のテーブルのみを使用している SQL では
エイリアスの付与も、オブジェクト名の修飾も不要です。

26
スナフキン 2020/01/28 (火) 11:16:24 837f8@06760

横から失礼。
はじめまして、スナフキンと申します。
少し気になって、期首在庫は必要ないのでしょうか?
それによってはすべてアウトになりそうで^^;;

一応、標準モジュールに
Public Function F_出庫数(int製品ID As Integer, str年月 As String, Optional bln集計区分 As Integer = 0) As Double

    Dim strQuery As String

    If bln集計区分 = 0 Then
        strQuery = "SELECT SUM(S.出庫数量) AS 出庫数量 FROM 出庫詳細 S LEFT JOIN 出庫 SH ON S.出庫ID=SH.出庫ID WHERE S.製品ID=" & int製品ID & " AND Format(SH.出庫日,'YYYYMM')='" & str年月 & "'"
    Else
        strQuery = "SELECT SUM(S.出庫数量) AS 出庫数量 FROM 出庫詳細 S LEFT JOIN 出庫 SH ON S.出庫ID=SH.出庫ID WHERE S.製品ID=" & int製品ID & " AND Format(SH.出庫日,'YYYYMM')<'" & str年月 & "'"
    End If

    Dim cn As New ADODB.Connection
    Dim rec As New ADODB.Recordset

    Set cn = CurrentProject.Connection
    Set rec = cn.Execute(strQuery)

    If rec.EOF = False Then
        F_出庫数 = Nz(rec.Fields("出庫数量"), 0)
    Else
        F_出庫数 = 0
    End If

    rec.Close: Set rec = Nothing
    cn.Close: Set cn = Nothing

End Function

Public Function F_入庫数(int製品ID As Integer, str年月 As String, Optional bln集計区分 As Integer = 0) As Double

(出庫と同じなので省略)

End Function

上記参照設定でADOにチェックです^^/

を用意したとして
製品IDを1
2020年1月の場合

前月在庫数=F_入庫数(1,"202001",1)-F_出庫数(1,"202001",1)
当月入庫数=F_入庫数(1,"202001")、当月出庫数=F_出庫数(1,"202001")
当月在庫数=F_入庫数(1,"202001",1)-F_出庫数(1,"202001",1)+F_入庫数(1,"202001")-F_出庫数(1,"202001")

上記でどうでしょうか?
クエリーでも使用できると思いますし、少し工夫すれば、期首在庫にも対応できるはず^^;;

かな??

27
mayu 2020/01/29 (水) 19:33:07 修正 9b175@61ad5 >> 26

少し気になって、期首在庫は必要ないのでしょうか?
それによってはすべてアウトになりそうで^^;;

フック船長さんのテーブル構成だと、棚卸をおこなった時点で

 ・ 製品ID毎に、実在庫に対して過不足があった場合は
   過不足分の数量を登録したレコードを DB登録して 不整合を解消する。
 ・ 製品ID毎に、詳細テーブルは 実在庫分の数量を記載した1レコードのみ の状態にし、
   棚卸実行日以前の全レコードは、別の場所へバックアップした上で削除

のどちらかで実現可能でしょうし、
テーブル設計が きちんと出来ていることから
フック船長さんは こういった業務知識や手法を身につけている可能性が高いのではないか
というのが、私の見解です。 
 

上記でどうでしょうか?
クエリーでも使用できると思いますし、少し工夫すれば、期首在庫にも対応できるはず^^;;

N + 1 問題
に該当しています、とだけ。

29
フック船長 2020/04/17 (金) 10:38:47 修正 f3309@726d9

皆様お久しぶりです。
いろいろとありがとうございました。
特にmayu様、hiroton様、本当にありがとうございました。

作っていただきました構文を業務で使わせていただいております。
やっていく中で改善点があり、またこちらのサイトで教えていただくことがあるかと思います。
その際はよろしくお願いします。

上段で期首在庫が必要かという質問がありましたので私の見解を伝えさせていただきます。
私自身、簿記を勉強した経験(3級取得ですが…)から、先入先出法の考え方を持っております。
テーブルには入ってませんがで入庫単価(仕入単価)・出庫単価(売上単価)のフィールドを作り、
クエリで入庫金額、出庫金額(売上金額)、期首前在庫単価、期首前在庫価格を作れば
物の流れやお金の流れが分かりやすくなるのではないかと思ったからです。
いずれはここまでもっていけたらと思っていますが……

参考サイト
https://petit-blog.com/boki/shikurikurishi/