>> 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 】
指定月のパラメータは
フォームのコントロールによる 日付の入力 を想定していますけど
入力をスキップすると、自動的に現在の月が設定されます。
通報 ...