#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
Надеюсь, кто-нибудь сможет пролить свет на проблему, которую я пытаюсь решить.
Типы
Type
------
'Type1'
'Type2'
'Type3'
Коды
Code | ID | Type
---------------------
ABC | 1234 | 'Type1'
ABC | 1234 | 'Type2'
CDE | 2345 | 'Type1'
CDE | 2345 | 'Type3'
EFG | 3456 | 'Type2'
Я хотел бы иметь возможность определять те пары Код / идентификатор, в которых отсутствует определенный тип.
Результат этого запроса должен выдать.
Code | ID | Type
--------------------
ABC | 1234 | 'Type3'
CDE | 2345 | 'Type2'
EFG | 3456 | 'Type1'
EFG | 3456 | 'Type3'
Комментарии:
1. Я не думаю, что это возможно с простым SQL
2. @RedGuy11 ты так думаешь?
3. Где полный список всех пар <Код, идентификатор>? Без этого ваша цель невозможна. У вас есть одно предложение, которое предполагает , что полный список — это просто все отдельные пары в вашей таблице. Это безопасно?
Ответ №1:
Для этого вам нужна условная агрегация:
SELECT
c.Code,
c.ID,
t.Type
FROM Types t
CROSS APPLY (
SELECT *
FROM Codes c
CROSS APPLY (VALUES (CASE WHEN c.Type = T.Type THEN 1 END) ) AS v (IsMatch)
GROUP BY Code, ID
HAVING COUNT(IsMatch) = 0
) c;
Другим вариантом является перекрестное объединение возможных идентификаторов с типами, а затем EXCEPT
удаление существующих. Проблема в том, что это означает повторное сканирование таблицы:
SELECT
c.Code,
c.ID,
t.Type
FROM Types t
CROSS JOIN (
SELECT DISTINCT Code, ID
FROM Codes c
) c
EXCEPT
SELECT
c.Code,
c.ID,
c.Type
FROM Codes c;
Комментарии:
1. Спасибо @Charlieface — первый запрос жалуется на то, что в агрегированном выражении, содержащем внешнюю ссылку, указано несколько столбцов. Второй запрос работает хорошо.
2. Исправлено. Я думаю, что первый запрос лучше из-за только одного сканирования.
Ответ №2:
Обычно я подхожу к этому, используя a CROSS JOIN
для генерации всех комбинаций и LEFT JOIN
(или NOT EXISTS
для удаления существующих:
SELECT c.Code, c.ID, t.Type
FROM (SELECT DISTINCT Code, Id FROM Codes c
) c CROSS JOIN
Types t LEFT JOIN
codes
ON codes.id = c.id AND codes.type = t.type
WHERE codes.code IS NULL;
Если у вас есть отдельный список кодов (который у вас должен быть), вы можете использовать его вместо SELECT DISTINCT
.
Ответ №3:
как насчет этого?
select Code, ID , Type
from youtable
where 'Type' = '' or `Type` IS NULL
или это?
select Code, ID , t.typeid
from youtable y
left join Types t on y.typeid = t.typeid
where t.typeid IS NULL
Комментарии:
1. Это не отвечает на вопрос
2. @Charlieface: Почему нет? Вы считаете, что это неправильный ответ? Если да, то чего не хватает участнику? Предоставление конструктивной обратной связи поможет им улучшить свой ответ, если это необходимо.