Используйте один запрос выбора вместо запроса + подзапрос - PullRequest
1 голос
/ 28 октября 2019

SQL Server 2014, данные были изменены для защиты данных. Я надеюсь, что нижеприведенное имеет смысл.

Я должен искать в таблице все категории с умеренным риском. Затем мне нужно перейти в другую таблицу (тест) и получить те умеренные категории, где только тест Тоби не прошел. Категории в этой первой таблице уникальны.

Таким образом, в приведенных ниже примерах данных категории 4 и 5 относятся к категории «Умеренный риск», и обе имеют также Тоби с результатом Fail в тестовой таблице.

Однако я хочу исключить категорию 4 из моего окончательного вывода, потому что в этой категории также есть тест Билла, который не прошел.

Моя цель - показать только категорию 5 в качестве вывода. Я могу сделать это с помощью запроса и подзапроса, где подзапрос возвращает категории 4 и 5 и основные фильтры запросов по этому. Но можно ли как-то добиться того же с помощью одного запроса?

Обновление:

Мой текущий запрос приведен ниже. Для этого поста мне пришлось немного поразмыслить, надеюсь, этого достаточно. По сути, подзапрос извлекает все категории, в которых был выполнен неудачный тест для умеренной категории, а основной запрос отфильтровывает любые категории с другими сбоями.

select tt.category, tt.[name]
from test_table mt
where tt.category in (select mt.category
                      from main_table mt
                      inner join test_table tt on tt.category = mt.category
                      where mt.risk= 'Moderate' and tt.result = 'Fail')
  and tt.[name] <> 'Toby'
  and tt.[result] = 'Fail'

Вывод:

category    risk
----------------------
1           Minimal
2           Critical
3           Elevated
4           Moderate
5           Moderate


category    name    result
-------------------------------
1           Mark    Pass
1           Bill    No Result
1           John    Pass
1           Toby    Pass

2           Mark    Pass
2           Bill    No Result
2           John    Fail
2           Toby    Pass

3           Mark    Pass
3           Bill    No Result
3           John    Pass
3           Toby    Pass

4           Mark    Pass
4           Bill    Fail
4           John    Pass
4           Toby    Fail

5           Mark    Pass
5           Bill    Pass
5           John    Pass
5           Toby    Fail

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

Присоединитесь к таблицам, group by category и установите условия в предложении HAVING:

select c.category
from categories c inner join test t
on c.category = t.category
where c.risk = 'Moderate'
group by c.category
having 
  sum(case when t.name = 'Toby' and t.result = 'Fail' then 1 else 0 end) > 0
  and 
  sum(case when t.name <> 'Toby' and t.result = 'Fail' then 1 else 0 end) = 0

или:

select c.category
from categories c inner join test t
on c.category = t.category
where c.risk = 'Moderate' and t.result = 'Fail'
group by c.category
having count(distinct t.name) = 1 and max(t.name) = 'Toby'

См. Демонстрационную версию . Результаты:

> | category |
> | -------: |
> |        5 |
0 голосов
/ 28 октября 2019

Довольно прямое прочтение вашего вопроса предполагает exists / not exists:

select c.*
from categories c
where c.risk = 'Moderate' and
      exists (select 1
              from tests t
              where t.category = c.category and
                    t.name = 'Toby' and
                    t.result = 'Fail'
             ) and
      not exists (select 1
                  from tests t
                  where t.category = c.category and
                        t.name <> 'Toby' and
                        t.result = 'Fail'
                 );

Условное агрегирование также является жизнеспособным решением - и решением, которое я предпочитаю, когда фильтр работает только на одномТаблица. Однако здесь используется фильтрация по двум таблицам, и это будет использовать индекс для test(category, result, name) и избежать внешней агрегации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...