以下查询在SQLite中对我有用。
SELECT Id, (SELECT Id
FROM Vehicles v
WHERE v.Id = t.VehicleId) AS VehId
FROM Transactions t
WHERE t.VehicleId IS NOT NULL AND VehId IS NULL;
但是在SQL Server中,它给我一个错误。
无效的列名“ VehId”。
然后编辑器在最后一个VehId
(但不是第一个)的下方放一个红色的波浪线。
如您所料,Vehicles.Id
是主键。我试图在Transactions
中找到所有未引用Vehicles
中任何行的外键。最好的方法是什么?
答案 0 :(得分:4)
您可以使用LEFT OUTER JOIN
查找不匹配的记录。
SELECT Id, v.Id AS VehId
FROM Transactions t
LEFT OUTER JOIN Vehicles v ON v.Id = t.VehicleId
WHERE t.VehicleId IS NOT NULL AND v.Id IS NULL
这保留了VehId
列,但是由于您知道它将始终为NULL
,因此可以通过子查询找到一组相似的数据。这将为您提供所有相同的行,但缺少VehId列-如果出于某种原因需要它,您始终可以对其进行硬编码。
SELECT Id
FROM Transactions t
WHERE t.VehicleId IS NOT NULL
AND t.VehicleId NOT IN (SELECT Id FROM Vehicles WHERE Id IS NOT NULL)
这将返回所有带有未知(但不为NULL)VehicleId的交易
答案 1 :(得分:2)
我认为您的查询可以简化为LEFT JOIN
反模式:
SELECT t.Id
FROM Transactions t
LEFT JOIN Vehicles v ON v.Id = t.VehicleId
WHERE t.VehicleId IS NOT NULL AND v.Id IS NULL
另一种选择是对关联子查询使用NOT EXISTS
条件:
SELECT Id
FROM Transactions t
WHERE
t.VehicleId IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM Vehicles v WHERE v.Id = t.VehicleId)
答案 2 :(得分:2)
您不能在where子句中引用列别名,这就是查询失败的原因。
看着它,我认为这可能是您要寻找的东西,它实质上复制了一个左联接,其中右表中的列不匹配。
SELECT Id, (SELECT Id
FROM Vehicles v
WHERE v.Id = t.VehicleId and v.id is null) AS VehId
FROM Transactions t
WHERE t.VehicleId IS NOT NULL;
答案 3 :(得分:2)
查询的问题在于,在SQL Server中,列列表是在WHERE子句之后评估的。这就是为什么您不能从WHERE子句引用列别名的原因。
有几种方法可以重写查询。这是其中的三个。
SELECT *
FROM (
SELECT Id, (SELECT Id
FROM Vehicles v
WHERE v.Id = t.VehicleId) AS VehId
FROM Transactions t) x
WHERE VehicleId IS NOT NULL AND VehId IS NULL;
SELECT Id, VehId
FROM Transactions t
OUTER APPLY (SELECT Id
FROM Vehicles v
WHERE v.Id = t.VehicleId) v(VehId)
WHERE t.VehicleId IS NOT NULL AND VehId IS NULL;
SELECT Id, NULL AS VehId
FROM Transactions t
WHERE t.VehicleId IS NOT NULL
AND NOT EXISTS (SELECT Id
FROM Vehicles v
WHERE v.Id = t.VehicleId);
答案 4 :(得分:1)
即使您的代码有效,为什么还要在结果中的第二列VehId
内填充null
呢?
当然,您可以进行LEFT
联接或使用其他方法,但是如果您想使其像代码一样简单,请从SELECT
列表中删除该列并将其移至WHERE
子句:
SELECT t.Id
FROM Transactions t
WHERE
t.VehicleId IS NOT NULL
AND
(SELECT v.Id FROM Vehicles v WHERE v.Id = t.VehicleId) IS NULL;
答案 5 :(得分:1)
使用NOT EXISTS
:
SELECT Id
FROM Transactions t
WHERE t.VehicleId IS NOT NULL AND
NOT EXISTS (SELECT Id
FROM Vehicles v
WHERE v.Id = t.VehicleId
);
这不仅是标准的SQL,而且在声明vehicles.id
为主键的任何数据库上都应具有良好的性能。