Запрос работает на SQLite, но не работает на SQL Server - PullRequest
0 голосов
/ 19 сентября 2019

Следующий запрос работает для меня в 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.Какой лучший способ сделать это?

Ответы [ 6 ]

4 голосов
/ 19 сентября 2019

Вы можете использовать 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

2 голосов
/ 19 сентября 2019

Проблема с вашим запросом состоит в том, что в SQL Server список столбцов оценивается после предложения WHERE.Вот почему вы не можете ссылаться на псевдоним столбца из предложения WHERE.

Существует несколько способов переписать запрос.Вот 3 из них.

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); 
2 голосов
/ 19 сентября 2019

Вы не можете ссылаться на псевдонимы столбцов в выражениях 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;
2 голосов
/ 19 сентября 2019

Я думаю, что ваш запрос может быть упрощен как LEFT JOIN antipattern:

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)
1 голос
/ 19 сентября 2019

Использование 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 объявлен как первичный ключ.

1 голос
/ 19 сентября 2019

Даже если ваш код сработал, зачем вам второй столбец 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...