Microsoft Access 掲示板

在庫数の算出 / 23

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

通報 ...