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]

我如何实现这一目标?(微软 SQL 服务器 2008)

4

2 回答 2

1

您的所有子查询在 where 子句中包含以下内容:INV1.WhsCode = [%2]

这意味着您可以像这样返回 [%2] 而不是 INV1.WhsCode:

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

这假定 [%2] 和其他类似的令牌被应用程序替换为 SQL Server 理解的东西,然后再发送以执行。

于 2012-10-18T13:38:53.393 回答
1

我知道您的查询有很多错误/效率低下的问题,但我还是会回答,因为这将有助于回答您提出的问题。

您需要尽可能避免相关子查询,有时它们是不可避免的,也是最好的解决方案,但是我经常在 JOIN 可以完成相同工作并且优化器会更好地处理 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 并且没有匹配项。最好的方法是使用类似于他的方法将每个日期转换为每个月的第一天:

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 回答