这在MS Access中非常有效。 为什么不在MS SQL Server中?
你能帮我解决吗?
select *
from tblPROestoque
where idproduto = 8183
order by identrada desc
select top(1) *
from tblPROestoque
where idproduto = 8183
order by identrada desc
select *
from tblPROproduto pr
left join (select top(1) idproduto, valcusto
from tblproestoque
order by identrada desc) tmp on tmp.idproduto = pr.idproduto
where pr.idproduto = 8183
答案 0 :(得分:0)
我怀疑这里的问题是您对子查询如何工作的理解。我们有您的查询:
SELECT *
FROM tblPROproduto pr
LEFT JOIN (SELECT TOP (1)
idproduto,
valcusto
FROM tblproestoque
ORDER BY identrada DESC) tmp ON tmp.idproduto = pr.idproduto
WHERE pr.idproduto = 8183;
我们可以将其分为两个不同的部分:
SELECT TOP (1)
idproduto,
valcusto
FROM tblproestoque
ORDER BY identrada DESC;
然后:
SELECT *
FROM tblPROproduto pr
LEFT JOIN tmp ON tmp.idproduto = pr.idproduto
WHERE pr.idproduto = 8183;
这可能会向您解释为什么您的现有商品无法使用。我猜您在假设ON
上的tmp
子句是在子查询的SELECT
之前派生的。事实并非如此。子查询将被派生,然后是ON
。因此,tmp
的值将是上面查询中返回的值。
我怀疑您想要的是什么
SELECT *
FROM tblPROproduto pr
OUTER APPLY (SELECT TOP (1)
ca.idproduto,
ca.valcusto
FROM tblproestoque ca
WHERE ca.idproduto = pr.idproduto
ORDER BY ca.identrada DESC) tmp
WHERE pr.idproduto = 8183;
编辑:为OP添加了一些示例数据和说明,以帮助其理解:
USE Sandbox;
GO
CREATE TABLE Product (ID int IDENTITY(1,1),
Sku varchar(10),
ProductName varchar(25));
CREATE TABLE ProductOrder (ID int IDENTITY(1,1),
ProductID int,
OrderDate date,
NumberOrdered int);
INSERT INTO dbo.Product (Sku,
ProductName)
VALUES ('65432462','Lawn Mower'),
('98742347','Helicopter'),
('89465735','BBQ');
INSERT INTO dbo.ProductOrder (ProductID,
OrderDate,
NumberOrdered)
VALUES (1,'20180101',7),
(1,'20180708',19),
(2,'20180501',12),
(3,'20180804',27);
GO
SELECT *
FROM dbo.Product;
SELECT *
FROM dbo.ProductOrder;
GO
--Use the example the OP has in their post:
SELECT *
FROM dbo.Product P
LEFT JOIN (SELECT TOP 1 *
FROM dbo.ProductOrder
ORDER BY OrderDate DESC) PO ON PO.ProductID = P.ID
WHERE P.ID = 2;
--This returns NULLs for all the latter columns.
--Why?
--Inspect the subquery:
SELECT TOP 1 *
FROM dbo.ProductOrder
ORDER BY OrderDate DESC;
--Product ID 3? 3 != 2 so the ON clause fails:
--Demonstrate
SELECT *
FROM dbo.Product P
CROSS JOIN (SELECT TOP 1 * --CROSS JOIN joins all rows (creates a cartesian product)
FROM dbo.ProductOrder
ORDER BY OrderDate DESC) PO
WHERE P.ID = 2;
--The solution, use OUTER APPLY:
SELECT *
FROM dbo.Product P
OUTER APPLY (SELECT TOP 1 *
FROM dbo.ProductOrder oa
WHERE oa.ProductID = P.ID --WHERE clause, this is like your ON
ORDER BY oa.OrderDate DESC) PO
WHERE P.ID = 2;
GO
DROP TABLE dbo.ProductOrder;
DROP TABLE dbo.Product;
答案 1 :(得分:0)
@RafaelBueno,您基本上需要一个outer apply
。这在MSAcess中是不同的。
请参见以下修改内容:
让我知道它是否有效。
select *
from tblPROproduto pr
outer apply (select top(1) idproduto, valcusto
from tblproestoque tmp
where tmp.idproduto = pr.idproduto
order by identrada desc) tmp
where pr.idproduto = 8183