Sql server SQL SERVER-左联接不起作用。因为

Sql server SQL SERVER-左联接不起作用。因为,sql-server,Sql Server,这在MS Access中非常有效。 为什么不在MS SQL Server中 你能帮我解决吗 我怀疑这里的问题在于您对子查询如何工作的理解。我们有你的疑问: SELECT * FROM tblPROproduto pr LEFT JOIN (SELECT TOP (1) idproduto, valcusto FROM tblproestoque

这在MS Access中非常有效。 为什么不在MS SQL Server中

你能帮我解决吗


我怀疑这里的问题在于您对子查询如何工作的理解。我们有你的疑问:

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;
这可能会向你解释为什么你所拥有的不起作用。我猜您假定tmp上的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添加了一些示例数据和解释,以帮助他们理解:


@拉斐尔布诺,你基本上需要一个外部应用程序。这在MSAccess中是不同的

见下文:

让我知道它是否有效

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

该链接指向Youtube。你的问题在哪里?以文本的形式发布。什么是with不起作用?我猜您的子查询不会返回您认为它会返回的结果,因为它没有where子句,而是您发布的前两个查询。尝试单独运行子查询并查看它返回的结果。idproduct,valcusto在左join上返回null,因为前1个查询也应该有where子句。on不能用于APPLY,并且这不会阻止在on之前解析子查询。如果子查询有效,则您是对的。现在已编辑。@Larnu,是的,有这个错误。@MEdwin您的解决方案成功了。非常感谢,我的朋友。谢谢大家helped@Larnu谢谢你的帮助和解释。他们帮了很多忙!有一个语法错误。关键字“WHERE”附近的语法不正确。@RafaelBueno抱歉,我错过了别名。伙计们,我不明白为什么这个简单的查询不能像Access一样完美地工作。表字段有什么问题吗?@RafaelBueno原因是子查询总是从tblproestoque返回前1,按identrada降序排列,而不管idproduto的值是多少。返回的行很可能没有idproduto的值8183,因此ON子句为false,并且没有返回值。@RafaelBueno希望该示例数据将帮助您了解SQL Server的工作方式。
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;
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