У меня скромный опыт работы с SQL (здесь используется MS SQL Server 2012), но это меня уклоняет.Я хочу вывести отдельные имена из таблицы (ранее успешно созданной из объединения), в которой отсутствуют некоторые обязательные записи, но при условии наличия другой аналогичной записи.Для любого, у кого есть местоположение 90, я хочу проверить, что у них также есть местоположения 10 и 20 ...
Например, рассмотрим следующую таблицу:
Name |Number |Location
--------|-------|--------
Alice |136218 |90
Alice |136218 |10
Alice |136218 |20
Alice |136218 |40
Bob |121478 |10
Bob |121478 |90
Chris |147835 |20
Chris |147835 |90
Don |138396 |20
Don |138396 |10
Emma |136412 |10
Emma |136412 |20
Emma |136412 |90
Fred |158647 |90
Gay |154221 |90
Gay |154221 |10
Gay |154221 |30
Итак, формально я хотел быполучить имена (и номера) тех записей в таблице, которые:
- имеют запись в местоположении 90
- и не имеют всех других необходимых записей местоположения - в этом случаетакже 10 и 20.
Таким образом, в приведенном выше примере
- Алиса и Эмма не выводятся по этому запросу, они имеют записи для 90, 10 и 20 (все присутствующиеи правильно, мы игнорируем запись местоположения 40).
- Дон не выводится этим запросом, у него нет записи для местоположения 90.
- Боб и Гай выводятся этим запросом,они оба пропускают местоположение 20 (мы игнорируем запись о местоположении гея 30).
- Крис выводится по этому запросу, он пропускает местоположение 10.
- Фред выводится по этому запросу, он отсутствуетместоположения 10 и 20.
Желаемым результатом запроса являетсяпеределать что-то вроде:
Name |Number |Location
--------|-------|--------
Bob |121478 |20
Chris |147835 |10
Fred |158647 |10
Fred |158647 |20
Gay |154221 |20
Я пробовал несколько подходов с левым / правым объединением, где B.Key имеет значение null и выбирал из ... за исключением, но пока я не могу понять логическиподход правильный.В исходной таблице сотни тысяч записей и только несколько десятков пропущенных совпадений.К сожалению, я не могу использовать ничего, что подсчитывает записи, так как запрос должен быть привязан к конкретным местоположениям, и есть другие допустимые записи таблицы в других местоположениях, кроме желаемых.
Мне кажется, что правильный способ сделать эточто-то вроде левого внешнего соединения, но поскольку стартовая таблица является выходом другого соединения, требуется ли для этого объявление промежуточной таблицы, а затем внешнее соединение промежуточной таблицы с ее собственным?Обратите внимание, что нет необходимости заполнять какие-либо пробелы или вводить элементы в таблицу.
Любой совет будет очень признателен.
=== Ответьте и используйте код, вставленный здесь ===
--STEP 0: Create a CTE of all valid actual data in the ranges that we want
WITH ValidSplits AS
(
SELECT DISTINCT C.StartNo, S.ChipNo, S.TimingPointId
FROM Splits AS S INNER JOIN Competitors AS C
ON S.ChipNo = C.ChipNo
AND (
S.TimingPointId IN (SELECT TimingPointId FROM @TimingPointCheck)
OR
S.TimingPointId = @TimingPointMasterCheck
)
),
--STEP 1: Create a CTE of the actual data that is specific to the precondition of passing @TimingPointMasterCheck
MasterSplits AS
(
SELECT DISTINCT StartNo, ChipNo, TimingPointId
FROM ValidSplits
WHERE TimingPointId = @TimingPointMasterCheck
)
--STEP 2: Create table of the other data we wish to see, i.e. a representation of the StartNo, ChipNo and TimingPointId of the finishers at the locations in @TimingPointCheck
--The key part here is the CROSS JOIN which makes a copy of every Start/ChipNo for every TimingPointId
SELECT StartNo, ChipNo, Missing.TimingPointId
FROM MasterSplits
CROSS JOIN (SELECT * FROM @TimingPointCheck) AS Missing(TimingPointId)
EXCEPT
SELECT StartNo, ChipNo, TimingPointId FROM ValidSplits
ORDER BY StartNo