!!! いくつかの仮定を確認する
データベーススキーマから、次のようになります。
- 特定のレコードが複数存在する可能性があります(たとえば、複数の顧客が同じバーのサブセクションを購入した可能性があると想像できます)。
Sales
BatchNumber/BarNo
- 特定のレコードが複数存在する可能性があります(たとえば、同じバーの複数のセクションを「予約」することができます)。
Reservation
BatchNumber/BarNo
これらのテーブルに実際に複数のレコードがあるかどうかを確認するには、次のようにしてみてください。
SELECT CountOfDuplicates
FROM (SELECT COUNT(*) AS CountOfDuplicates
FROM Sales
GROUP BY BatchNumber & "," & BarNo)
WHERE CountOfDuplicates > 1
クエリがいくつかのレコードを返す場合は、重複があり、クエリが誤った値を返しているのはおそらくそのためです。
ゼロから始める
さて、クエリを機能させる秘訣は、表示したい主なデータを実際に考えて、そこから始めることです。
- 基本的に、在庫内のすべてのバーのリストが必要です。これらのバーの一部は販売されているか、予約されている可能性がありますが、そうでない場合は、在庫がある数量を表示する必要があります。あなたの現在のクエリはあなたにそれを決して示しません。
- 在庫のあるバーごとに、販売数量と予約数量をリストし、それらを組み合わせて、残りの在庫数を調べます。
ですから、あなたの中心的なデータは在庫のあるバーのリストであることは明らかです。
すべてをすぐに1つの大きなクエリにまとめようとするのではなく、これらの目標ごとに単純なクエリを作成し、それぞれの場合に適切なデータを取得することをお勧めします。
ただのバー
あなたが説明したことから、個々のバーはBarStock
テーブルに記録されます。
コメントで述べたように、私が理解していることから、配信されるすべてのバーには、BarStock
重複のない単一のレコードがテーブルにあります。したがって、在庫を測定する必要がある主なリストは次のBarStock
表です。
SELECT BatchNumber,
BarNo,
OrgLength
FROM BarStock
ただの販売
BatchNumber/BarNo
繰り返しになりますが、これは非常に簡単なはずです。各ペアで販売された全長を確認する必要があります。
SELECT BatchNumber,
BarNo,
Sum(QtySold) AS SumAvQtySold
FROM Sales
GROUP BY BatchNumber, BarNo
予約だけ
販売と同じ:
SELECT BatchNumber,
BarNo,
SUM(QtyReserved) AS Reserved
FROM Reservation
GROUP BY BatchNumber, BarNo
販売に対する元の在庫
これで、最初の2つのクエリを1つにまとめることができるはずです。データを連携させるためだけに、最適化しようとはしていません。
SELECT BarStock.BatchNumber,
BarStock.BarNo,
BarStock.OrgLength,
S.SumAvQtySold,
(BarStock.OrgLength - Nz(S.SumAvQtySold)) AS OnStock
FROM BarStock
LEFT JOIN (SELECT BatchNumber,
BarNo,
Sum(QtySold) AS SumAvQtySold
FROM Sales
GROUP BY BatchNumber, BarNo) AS S
ON (BarStock.BatchNumber = S.BatchNumber) AND (BarStock.BarNo = S.BarNo)
LEFT JOIN
まだ販売されていないバーの在庫があるかもしれないので、私たちはそうします。
私たちがやった場合INNER JOIN
、私たちは最終報告書でこれらを見逃していると思い、そもそもこれらのバーは決してそこになかったと信じるようになりました。
すべて一緒に
LEFT JOIN
これで、クエリ全体を予約済みのバーに対して別のクエリでラップして、最終結果を得ることができます。
SELECT BS.BatchNumber,
BS.BarNo,
BS.OrgLength,
BS.SumAvQtySold,
BS.OnStock,
R.Reserved,
(OnStock - Nz(Reserved)) AS Available
FROM (SELECT BarStock.BatchNumber,
BarStock.BarNo,
BarStock.OrgLength,
S.SumAvQtySold,
(BarStock.OrgLength - Nz(S.SumAvQtySold)) AS OnStock
FROM BarStock
LEFT JOIN (SELECT BatchNumber,
BarNo,
SUM(QtySold) AS SumAvQtySold
FROM Sales
GROUP BY BatchNumber,
BarNo) AS S
ON (BarStock.BatchNumber = S.BatchNumber) AND (BarStock.BarNo = S.BarNo)) AS BS
LEFT JOIN (SELECT BatchNumber,
BarNo,
SUM(QtyReserved) AS Reserved
FROM Reservation
GROUP BY BatchNumber,
BarNo) AS R
ON (BS.BatchNumber = R.BatchNumber) AND (BS.BarNo = R.BarNo)
Nz()
結合の右側にあるforアイテムの使用に注意してください。特定のペアのデータがない場合、Sales
またはの値は、実際の在庫数に関係なく、レンダリングされ、 nullになります。私たちが期待する結果ではないでしょう。Reservation
BatchNumber/BarNo
SumAvQtySold
Reserved
Null
OnStock
Available
Accessでクエリデザイナを使用すると、3つのクエリを個別に作成してから、それらを組み合わせる必要があります。
ただし、Query Designedは複数LEFT
のRIGHT
結合を処理するのがあまり得意ではないため、一度にすべてを記述できなかったと思います。
いくつかのコメント
@Remouが彼のコメントであなたに与えた情報を読むべきだと私は信じています。私にとって、このデータベースにはいくつかの不幸な設計上の選択があります。基本的な在庫データの取得は、在庫レコードを保持する列で
の単純なものと同じくらい簡単である必要があります。SUM()
通常、在庫を追跡する簡単な方法は、各株式取引を追跡することです。
- 入荷在庫レコードには+数量があります
- 出庫在庫レコードには-数量があります
- レコードには、部品/アイテム/バーの参照(またはID)、トランザクションの日時、および(複数の倉庫を管理する場合は)どの倉庫IDが関係しているかも追跡する必要があります。
したがって、すべてのアイテムの手元にある完全な在庫を知る必要がある場合、必要なのは次のようなものだけです。
SELECT BarID,
Sum(Quantity)
FROM StockTransaction
GROUP BY BarID
あなたの場合、それBatchNumber/BarNo
はあなたの自然キーですが、それらを別のBar
テーブルに保持することにはいくつかの利点があります。
- あなたはそれ
Bar.ID
を取り戻すためにBar.BatchNumber
そしてBar.BarNo
あなたがそれを必要とするところならどこでも使うことができます。
- 、およびテーブル
BarID
で外部キーとして使用できます。複合キーの複雑さを台無しにすることなく、結合が簡単になります。BarStock
Sales
Reservation
テーブル名やフィールドのスペースなど、Accessで許可されているものがあります。これにより、読みにくくなり(少なくとも間に保持する必要があるため[]
)、これらを表すVBA変数名との整合性が低下します。フィールドであり、テーブル名とフィールド名に英数字以外のものを受け入れない他のデータベースとは互換性がありません(後でサイズを大きくするか、データベースを他のアプリとインターフェースする必要があります)。
また、単一の命名規則に固執することで自分自身を助け、一貫性を保ちます。
- 大文字と小文字を一貫して混在させないでください。すべてにキャメルケースを使用するか、小文字または大文字を使用しますが、常にその規則に従ってください。
- テーブルに単数形(または複数形)で名前を付けますが、一貫性を保ちます。
Part
私は、の代わりにテーブルのような単数を使用することを好みますParts
が、それは単なる慣例です(それは独自の理由があります)。
- 正しくつづります:そうで
Received
はありませんRecieved
。誰かがタイプミスをしたという理由だけで、一部のクエリまたはVBAコードが機能しない理由をデバッグするときに、その間違いだけでコストがかかる可能性があります。
ID
各テーブルには列が必要です。通常、これはテーブル内の各レコードの一意性を保証する自動インクリメントになります。その慣習を守れば、外部キーは推測しやすくなり、読みやすくなります。ビジネス要件によって、2つの同一のものが突然見つかる可能性があるという事実を心配する必要はありBatchNumbers
ません。何らかの理由で、今は理解できません。
データベース設計については多くの議論がありますが、誰もが同意する特定の「ルール」があるので、私の推奨事項は次のことを目指して努力することです。
- シンプルさ:各テーブルが1種類のデータを記録し、他のテーブルからの冗長データが含まれていないことを確認します(正規化)。
- 一貫性:命名規則は重要です。何を選択しても、プロジェクト全体を通してそれに固執します。
- 明確さ:3歳以上の人や他の人が、300ページの仕様を読まなくても、テーブルの名前とフィールドを簡単に読んで、それらが何であるかを理解できるようにしてください。常に明確にすることは可能ではありませんが、それは努力すべきことです。