0

ここで SQL Server の初心者の質問! tbl_Sales、tbl_SalesItems、tbl_Products の 3 つのテーブルがあります。tbl_SalesItems は、各販売に追加された製品を格納し、製品コードによって tbl_Products に結合されます。tbl_Products の製品は、ProductGroup フィールドによって分類されます。環境的には、常に約 200 件の販売があり、販売ごとに 4 ~ 5 個のアイテムと 3000 個の製品があります。レコード数は非常に少ないですが、Sales および SalesItems データは継続的に変化しています。計算はライブ環境で 1 日に何百回も行われ、応答時間が重要になります。

具体的には、特定の製品グループごとのその販売のアイテム数に基づいて、各販売を分類したいと考えています。

商品グループ 13 の商品が 1 個、商品グループ 14 の商品が 0 個、商品グループ 16 の商品が 0 個の場合、販売は Type1 です。

商品グループ 13 の商品が 0 個、商品グループ 14 の商品が 1 個、商品グループ 16 の商品が 0 個の場合、販売は Type2 です。

それ以外の販売は Type0

Access/VBA を使用していた場合、3 つの製品グループのそれぞれについて、その販売内のアイテムの数である 3 つのレコードの 1 つのレコードセットを作成し、レコードをループして値を取得し、タイプを決定します。

これが SQL サーバー関数またはストアド プロシージャで可能かどうかはわかりません。現在、3 つの個別の SELECT ステートメントを実行し、結果を次のように評価しています。

ALTER FUNCTION [dbo].[fSaleATCType] ( @SaleID int)
RETURNS tinyint
BEGIN

declare @InOutWashCount int
declare @OutWashCount int
declare @ExtraCount int
declare @ATCType tinyint

SET @InOutWashCount = 
    (
    SELECT COUNT(dbo.tbl_SalesItems.SaleItemCode) AS CountItems
    FROM        dbo.tbl_SalesItems LEFT OUTER JOIN
                dbo.tbl_Products ON dbo.tbl_SalesItems.SaleItemCode = dbo.tbl_Products.ProductCode
    WHERE       (dbo.tbl_SalesItems.SaleID = @SaleID) AND (dbo.tbl_Products.ProductGroup = 13)
    )

SET @OutWashCount = 
    (
    SELECT COUNT(dbo.tbl_SalesItems.SaleItemCode) AS CountItems
    FROM        dbo.tbl_SalesItems LEFT OUTER JOIN
                dbo.tbl_Products ON dbo.tbl_SalesItems.SaleItemCode = dbo.tbl_Products.ProductCode
    WHERE       (dbo.tbl_SalesItems.SaleID = @SaleID) AND (dbo.tbl_Products.ProductGroup = 14)
    )

SET @ExtraCount = 
    (
    SELECT COUNT(dbo.tbl_SalesItems.SaleItemCode) AS CountItems
    FROM        dbo.tbl_SalesItems LEFT OUTER JOIN
                dbo.tbl_Products ON dbo.tbl_SalesItems.SaleItemCode = dbo.tbl_Products.ProductCode
    WHERE       (dbo.tbl_SalesItems.SaleID = @SaleID) AND (dbo.tbl_Products.ProductGroup = 16)
    )

SET @ATCType = 0

if @InOutWashCount = 1 and @OutWashCount = 0 and @ExtraCount = 0
    SET @ATCType = 1

if @InOutWashCount = 0 and @OutWashCount = 1 and @ExtraCount = 0
    SET @ATCType = 2

RETURN @ATCType

END

そこから 3 つの SELECT を実行しますか?

これが最善の方法ですか?temptable を作成してから、そこから 3 つの SELECT を実行したほうがよいでしょうか? または、次のようなビューを作成します

SELECT      dbo.tbl_SalesItems.SaleID, 
        dbo.tbl_Products.ProductGroup, 
        COUNT(dbo.tbl_SalesItems.SaleItemCode) AS CountItems

FROM        dbo.tbl_SalesItems LEFT OUTER JOIN
            dbo.tbl_Products ON dbo.tbl_SalesItems.SaleItemCode = dbo.tbl_Products.ProductCode

GROUP BY    dbo.tbl_Products.ProductGroup, 
        dbo.tbl_SalesItems.SaleID

そこから 3 つの SELECT を実行しますか?

読んでくれてありがとう!これが理にかなっていることを願っています。どんな提案も大歓迎です!

ビッグジム

4

1 に答える 1

0

私はあなたを正しく理解していることを願っていますが、このようなクエリが必要かもしれません (ところで、私はこれをテストしておらず、COUNT の使用について確信が持てません - 数値 > 1 をカウントするとどうなりますか?):

(編集:いくつかのテストデータと結果を追加して、状況を明確にし、いくつかのコピーアンドペーストエラーをデバッグしました。)

基本的に、各左結合は、特定のグループの販売アイテム製品を表し、case ステートメントはロジックのドライバーです。

テストして遊んでみてください。上部の一時テーブルを使用すると、独自のテスト データを使用してさまざまなケースを試すことができます。

また、WHERE 句を削除し、group by を追加して、すべてのテスト データを一目で確認できるようにしました...

DECLARE @SaleId int
DECLARE @tbl_SalesItems AS TABLE(SaleID int, SaleItemCode varchar(10))
DECLARE @tbl_Products AS TABLE(ProductGroup int, ProductCode varchar(10))

INSERT INTO @tbl_SalesItems(SaleID, SaleItemCode) VALUES (1,'Product1')
INSERT INTO @tbl_SalesItems(SaleID, SaleItemCode) VALUES (2,'Product2')
INSERT INTO @tbl_SalesItems(SaleID, SaleItemCode) VALUES (3,'Product1')
INSERT INTO @tbl_SalesItems(SaleID, SaleItemCode) VALUES (3,'Product2')
INSERT INTO @tbl_SalesItems(SaleID, SaleItemCode) VALUES (3,'Product3')

INSERT INTO @tbl_Products(ProductGroup, ProductCode) VALUES (13, 'Product1')
INSERT INTO @tbl_Products(ProductGroup, ProductCode) VALUES (14, 'Product2')
INSERT INTO @tbl_Products(ProductGroup, ProductCode) VALUES (16, 'Product3')
INSERT INTO @tbl_Products(ProductGroup, ProductCode) VALUES (16, 'Product4')

SET @SaleId = 1

SELECT  si.SaleId
       ,CASE
        WHEN COUNT(pg13.ProductCode) = 1 AND COUNT(pg14.ProductCode) = 0 AND COUNT(pg16.ProductCode)  = 0
        THEN 1
        WHEN COUNT(pg13.ProductCode) = 0 AND COUNT(pg14.ProductCode) = 1 AND COUNT(pg16.ProductCode)  = 0
        THEN 2
        ELSE 0 END AS ATCType
FROM        @tbl_SalesItems si
LEFT JOIN   @tbl_Products  pg13
    ON si.SaleItemCode = pg13.ProductCode
    AND (pg13.ProductGroup = 13)
LEFT JOIN   @tbl_Products  pg14
    ON si.SaleItemCode = pg14.ProductCode
    AND (pg14.ProductGroup = 14)
LEFT JOIN   @tbl_Products  pg16
    ON si.SaleItemCode = pg16.ProductCode
    AND (pg16.ProductGroup = 16)
--WHERE si.SaleId = @SaleId
GROUP BY si.SaleId

結果:

SaleId  ATCType
1       1
2       2
3       0
4       2
于 2013-08-09T12:37:00.563 に答える