私は現在、SQL を使用してサードパーティの請求システムのバックエンドを利用する Delphi でアプリを開発しているため、そのレポート機能を拡張できます。私はプログラミングの Delphi 側にかなり精通していると思いますが、SQL は私にとって初めてなので、このフォーラムやその他のリソースの多大な助けを借りて、自分ができると思っていた以上に多くのことを独学することができました。
ほとんどのデータはいくつかのテーブルから引き出されます (私はその側に問題がないので、それらの詳細で投稿を詰まらせることはありません) が、原価を取得する際に問題があります。過去のコスト価格を追跡するテーブルに保存されるため、各製品 (16,000 以上) には数百のレコードが存在する可能性がありますが、請求書の日付に最も近い (<=) 各製品のコストのみが必要です。 . 関数は次のとおりです。
CREATE FUNCTION dbo.CostAtDate ( @costdate AS datetime , @product AS int )
RETURNS decimal(18,2)
AS
BEGIN
DECLARE @result decimal(18,2)
SET @result = (
Select Top 1
BASE_InventoryCostLogDetail.AverageCostAfter
From
BASE_InventoryCostLogDetail
Where
CreatedDttm < @costdate And CreatedDttm > DATEADD(month,-1,@costDate) And
ProdId = @product
Order By
CreatedDttm Desc)
RETURN @result
END
そして、これがクエリの 1 つです (いくつかの異なるクエリがありますが、すべて同じ構造に基づいています)。
Select
BASE_Customer.Name,
SO_SalesOrder.OrderNumber,
SO_SalesOrderInvoice_Line.Description,
SO_SalesOrderInvoice_Line.UnitPrice,
Case SO_SalesOrderInvoice_Line.ItemTaxCodeId
When '100' Then (SO_SalesOrderInvoice_Line.UnitPrice / 11) * 10
Else SO_SalesOrderInvoice_Line.UnitPrice End As exgst,
SO_SalesOrderInvoice_Line.QuantityUom,
SO_SalesOrderInvoice_Line.QuantityDisplay,
Case SO_SalesOrderInvoice_Line.QuantityUom
When 'cases.' Then dbo.CostAtDate(SO_SalesOrder.OrderDate,
SO_SalesOrderInvoice_Line.ProdId) * BASE_Product.SoUomRatioStd
Else dbo.CostAtDate(SO_SalesOrder.OrderDate,
SO_SalesOrderInvoice_Line.ProdId) End As cost,
Case SO_SalesOrderInvoice_Line.QuantityUom
When 'cases.' Then ((dbo.CostAtDate(SO_SalesOrder.OrderDate,
SO_SalesOrderInvoice_Line.ProdId) * BASE_Product.SoUomRatioStd) / 11) * 10
Else (dbo.CostAtDate(SO_SalesOrder.OrderDate,
SO_SalesOrderInvoice_Line.ProdId) / 11) * 10 End As exgstcost,
BASE_Product.SoUomRatioStd,
BASE_Product.Name As Name1,
SO_SalesOrder.OrderDate
From
BASE_Customer Inner Join
SO_SalesOrder On SO_SalesOrder.CustomerId = BASE_Customer.CustomerId
Inner Join
SO_SalesOrderInvoice_Line On SO_SalesOrderInvoice_Line.SalesOrderId =
SO_SalesOrder.SalesOrderId Inner Join
BASE_Product On SO_SalesOrderInvoice_Line.ProdId = BASE_Product.ProdId
Where
SO_SalesOrder.OrderDate Between '20131028' And '20131029'
これで、選択した範囲に数件の請求書しかない場合は問題なく動作しますが、関数がレコードごとに最低 3 回呼び出されることを考えると、レポートを 1 日以上にわたって作成しようとすると、パフォーマンスが実際に低下します。日 (2 週間にわたるレポートが必要になることがよくあります)。
残念ながら、これはサード パーティの製品であるため (興味のある人は inFlow Inventory を参照してください)、テーブル構造を変更することはできません。
より効率的な結合、派生テーブル (概念は理解していますが、実行したことはありません) を使用するか、クエリ全体を書き直してパフォーマンスを大幅に向上させる方法はありますか?