0

次の SQL クエリから追加の列 INV1.WhsCode を返すために、ユーザー クエリを変更しようとしています。

SELECT  T0.CardCode,
        T2.CardName,
        T0.CodeBars,
        T0.ItemCode,
        T0.ItemName,
        T3.Price AS [POS Price],
        T1.AvgPrice,
        T1.OnHand,
        T1.MinStock,
        T1.MaxStock,
        T0.NumInBuy AS Packsize,
        T0.LstSalDate,
        (
            SELECT SUM(Quantity) AS Expr1
            FROM dbo.INV1
            INNER JOIN OINV
                    ON INV1.DocEntry = OINV.DocEntry
            WHERE INV1.ItemCode = T0.ItemCode
                    AND INV1.WhsCode = [%2]
                    AND Month(OINV.DocDate) = month(GetDate())
        ) AS [Current Period],
        (
            SELECT SUM(Quantity) AS Expr1
            FROM dbo.INV1
            INNER JOIN OINV
                    ON INV1.DocEntry = OINV.DocEntry
            WHERE INV1.ItemCode = T0.ItemCode
                    AND INV1.WhsCode = [%2]
                    AND Month(OINV.DocDate) = month(GetDate()) - 1
        ) AS [Previous Period],
        (
            SELECT SUM(Quantity) AS Expr1
            FROM dbo.INV1
            INNER JOIN OINV
                    ON INV1.DocEntry = OINV.DocEntry
            WHERE INV1.ItemCode = T0.ItemCode
                    AND INV1.WhsCode = [%2]
                    AND Month(OINV.DocDate) = month(GetDate()) - 2
        ) AS [60-90],
        (
            SELECT TOP 1 OPDN.DocDate AS Expr1
            FROM dbo.PDN1
            INNER JOIN OPDN
                    ON PDN1.DocEntry = OPDN.DocEntry
            WHERE PDN1.ItemCode = T0.ItemCode
            ORDER BY OPDN.DocDate DESC
        ) AS LastGRNDate
FROM    OITM T0
        INNER JOIN OITW T1
            ON T0.ItemCode = T1.ItemCode
        INNER JOIN OCRD T2
            ON T0.CardCode = T2.CardCode
        INNER JOIN ITM1 T3
            ON T0.ItemCode = T3.ItemCode
        INNER JOIN OWHS T4
            ON T1.WhsCode = T4.WhsCode
        INNER JOIN OITB T5
            ON T0.ItmsGrpCod = T5.ItmsGrpCod
WHERE   T3.PriceList = '3'
        AND T4.WhsName = [%0]
        AND T5.ItmsGrpNam = [%1]

どうすればこれを達成できますか? (MS SQL Server 2008)

4

2 に答える 2

1

あなたが尋ねなかったことを私が知っているあなたの質問には多くの間違った/非効率的なことがあります、しかしそれはあなたが尋ねた質問に答えるのを助けるのでとにかく答えるつもりです。

可能な限り相関サブクエリを回避する必要があります。それらが避けられない場合があり、最善の解決策ですが、JOINが同じ仕事をし、オプティマイザーが参加をはるかにうまく処理する場所でそれらをよく見かけます。たとえば、次のようになります。

SELECT  (
            SELECT TOP 1 OPDN.DocDate AS Expr1
            FROM dbo.PDN1
            INNER JOIN OPDN
                    ON PDN1.DocEntry = OPDN.DocEntry
            WHERE PDN1.ItemCode = T0.ItemCode
            ORDER BY OPDN.DocDate DESC
        ) AS LastGRNDate
FROM    OITM T0

これにより、各行のサブクエリが評価されますが、次のように書き直した場合は次のようになります。

SELECT  LastGRN.LastGRNDate
FROM    OITM TO
        LEFT JOIN
        (   SELECT  PDN1.ItemCode, [LastGRNDate] = MAX(OPDN.DocDate)
            FROM    dbo.PDN1
                    INNER JOIN OPDN
                        ON PDN1.DocEntry = OPDN.DocEntry
            GROUP BY PDN1.ItemCode
        ) LastGRN
            ON LastGRN.ItemCode = T0.ItemCode

同じ結果が得られますが、はるかに効率的な方法で評価されます。

次の欠点は、MONTH(GETDATE())-1を使用して2か月前に取得する方法です。1月には、これは0に評価され、一致するものはありません。これを行うための最良の方法は、彼に似たものを使用して、各日付を毎月1日に変換することです。

SELECT  [FirstOfThisMonth] = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0),
        [FirstOfLastMonth] = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE() - 1), 0)

相関サブクエリではなく結合の同じ原則を数量列に適用することもできます。これにより、WhsCode列にアクセスできます。必須ではありませんが、一般的なテーブル式を使用してクエリをクリーンアップしました(その上)

WITH Quantities AS
(   SELECT  [DocMonth] = DATEADD(MONTH, DATEDIFF(MONTH, 0, IONV.DocDate),
            Inv1.WhsCode,
            ItemCode,
            [Quantity] = SUM(Quantity)
    FROM    dbo.Inv1
            INNER JOIN OINV
                ON Inv1.DocEntry = OINV.DocEntry
    GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, IONV.DocDate), WhsCode, itemCode
)
SELECT  T0.ItemCode,
        [Current Period] = COALESCE(Cur.Quantity, 0),
        [Previous Period] = COALESCE(prev.Quantity, 0),
        [60-90] = COALESCE(prev2.Quantity, 0)
FROM    OITM T0
        LEFT JOIN Quantities cur
            ON cur.ItemCode = T0.ItemCode
            AND cur.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
            AND Cur.WhsCode = [%2]
        LEFT JOIN Quantities prev
            ON prev.ItemCode = T0.ItemCode
            AND prev.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 1, 0)
            AND prev.WhsCode = [%2]
        LEFT JOIN Quantities prev2
            ON prev2.ItemCode = T0.ItemCode
            AND prev2.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 2, 0)
            AND prev2.WhsCode = [%2]

これらすべてを最終的なクエリに組み合わせると、次のようになります。

SELECT  T0.CardCode,
        T2.CardName,
        T0.CodeBars,
        T0.ItemCode,
        T0.ItemName,
        T3.Price,
        T1.AvgPrice,
        T1.OnHand,
        T1.MinStock,
        T1.MaxStock,
        T0.NumInBuy AS Packsize,
        T0.LstSalDate
        [Current Period] = COALESCE(Cur.Quantity, 0),
        [Previous Period] = COALESCE(prev.Quantity, 0),
        [60-90] = COALESCE(prev2.Quantity, 0)
        LastGRN.LastGRNDate
FROM    OITM T0
        INNER JOIN OITW T1
            ON T0.ItemCode = T1.ItemCode
        INNER JOIN OCRD T2
            ON T0.CardCode = T2.CardCode
        INNER JOIN ITM1 T3
            ON T0.ItemCode = T3.ItemCode
        INNER JOIN OWHS T4
            ON T1.WhsCode = T4.WhsCode
        INNER JOIN OITB T5
            ON T0.ItmsGrpCod = T5.ItmsGrpCod
        LEFT JOIN Quantities cur
            ON cur.ItemCode = T0.ItemCode
            AND cur.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
            AND Cur.WhsCode = [%2]
        LEFT JOIN Quantities prev
            ON prev.ItemCode = T0.ItemCode
            AND prev.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 1, 0)
            AND prev.WhsCode = [%2]
        LEFT JOIN Quantities prev2
            ON prev2.ItemCode = T0.ItemCode
            AND prev2.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 2, 0)
            AND prev2.WhsCode = [%2]
        LEFT JOIN
        (   SELECT  PDN1.ItemCode, [LastGRNDate] = MAX(OPDN.DocDate)
            FROM    dbo.PDN1
                    INNER JOIN OPDN
                        ON PDN1.DocEntry = OPDN.DocEntry
            GROUP BY PDN1.ItemCode
        ) LastGRN
            ON LastGRN.ItemCode = T0.ItemCode
WHERE   T3.PriceList = '3'
AND     T4.WhsName = [%0]
AND     T5.ItmsGrpNam = [%1]

これはすべてテストされていないため、タイプミスやわずかな構文エラーが発生する可能性がありますが、同じ原則が適用されるはずです。

相関サブクエリのアイデアにまだ固執している場合は、APPLYそこから複数の列にアクセスできるようにするために使用できます。例えば

SELECT  T0.Code, cur.WhsCode, cur.Expr1 AS [Current Period]
FROM    OITM T0
        OUTER APPLY
        (   SELECT  INV1.WhsCode, SUM(Quantity) AS Expr1
            FROM    dbo.INV1
                    INNER JOIN OINV
                        ON INV1.DocEntry = OINV.DocEntry
            WHERE   INV1.ItemCode = T0.ItemCode
            AND     INV1.WhsCode = [%2]
            AND     MONTH(OINV.DocDate) = MONTH(GETDATE())
        ) cur
于 2012-10-18T14:43:42.363 に答える
1

すべてのサブクエリの where 句に次のものが含まれています: INV1.WhsCode = [%2]

つまり、INV1.WhsCode の代わりに、次のように [%2] を返すことができます。

SELECT  [%2] as WhsCode,
        T0.CardCode,
        T2.CardName,
        T0.CodeBars,
......

これは、[%2] と他の同様のトークンがアプリによって SQL Server が理解できるものに置き換えられてから、これが送信されて実行されることを前提としています。

于 2012-10-18T13:38:53.393 に答える