我正在尝试修改用户查询,以便从以下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)
答案 0 :(得分:1)
所有子查询都在where子句中包含以下内容:INV1.WhsCode = [%2]
这意味着您可以像这样返回[%2]而不是INV1.WhsCode:
SELECT [%2] as WhsCode,
T0.CardCode,
T2.CardName,
T0.CodeBars,
......
这假定[%2]和其他类似的令牌被应用程序替换为SQL Server可以理解的内容,然后再发送执行。
答案 1 :(得分: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并且没有比赛。最好的方法是使用类似于他的东西将每个日期转换为每月的第一个日期:
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
来允许您从中访问多个列。 e.g。
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