Запрос оператора SQL с вложенным предложением

#sql-server #tsql

#sql-сервер #tsql

Вопрос:

В целях презентации я изменяю имена таблиц и полей и упрощаю проблему SQL:

У нас есть таблица с именем A , содержащая только 2 столбца:

 Name   ServiceReceived
=========================
Mr A   Medical
Mr A   Dental
Mr A   HealthCare
Mr A   Special1
Mr B   Dental
Mr B   HealthCare
Mr C   Medical
Mr C   Dental
Mr C   HealthCare
Mr C   Special
Mr C   Special2 
  

Мне нужен список всех людей, которые пересмотрели медицинские или стоматологические.

А также получил один или два из Special1 и Special2

Я пытался

 where ServiceReceived in ('medical', 'dental')
  and ServiceReceived in ('Special1', 'Special2')
  

Но это не работает.

 ======================================
  

Ожидаемые результаты: (Как вы видите, MrB там нет, поскольку у него нет Special1 или Special2

  Name   ServiceReceived
    =========================
    Mr A   Medical
    Mr A   Dental
    Mr A   HealthCare
    Mr A   Special1 
    Mr C   Medical
    Mr C   Dental
    Mr C   HealthCare
    Mr C   Special
    Mr C   Special2 
  

Комментарии:

1. Укажите также ожидаемый результат.

2. Пожалуйста, прочтите это , чтобы получить несколько советов по улучшению вашего вопроса.

3. @jarlh Я далее объясню ожидаемые результаты, о которых идет речь. Спасибо

Ответ №1:

Вы можете использовать агрегацию и having предложение:

     select t.*
    from t
    group by Name
    having sum(case when ServiceRecived in ('Medical', 'Dental') then 1 else 0 end) > 0 and
           sum(case when ServiceRecived in ('Special1', 'Special2') then 1 else 0 end) between 1 and 2;
  

Если вы хотите просмотреть все подробности, вы можете использовать join , in или exists :

     select t.*
    from t
    where t.name in (select Name
                     from t
                     group by Name
                     having sum(case when ServiceRecived in ('Medical', 'Dental') then 1 else 0 end) > 0 and
                            sum(case when ServiceRecived in ('Special1', 'Special2') then 1 else 0 end) between 1 and 2
                    );
  

Комментарии:

1. Спасибо, я вписываю это в свой реальный SQL и дам вам знать!

2. Ваш SQL правильно устраняет MrB. Но только дайте мне результат в виде MRA и MrB. Я также хочу видеть все их имена служб.

3. Вот и все! Мой реальный код SQL очень сложный. но ваше решение применимо и к этому.

Ответ №2:

 

Select Name 
from 
(
Select Name,
       Sum(Case when ServiceRequested = 'Medical' then 1 else 0 end) as Medical,
       Sum(Case when ServiceRequested = 'Dental' then 1 else 0 end) as Dental,
       Sum(Case when ServiceRequested IN ('Special1','Special2') then 1 else 0 end) as Specials
from [dbo].[Services]
Group by Name
)s
Where  ( Medical >= 1 or Dental >= 1 ) AND Specials >= 1
  

Ответ №3:

Следующее решение работает с оператором таблицы пересечения SQL server.

 SELECT NAME 
FROM T 
WHERE ServiceReceived IN ('medical', 'dental') 
INTERSECT 
SELECT NAME 
FROM T WHERE 
ServiceReceived IN ('Special1', 'Special2')
  

Ответ №4:

Это должно сработать.

 SELECT NAME
FROM A
WHERE
    NAME IN (SELECT NAME FROM A AS A2 WHERE A2.ServiceReceived IN ('medical', 'dental'))
    AND NAME IN (SELECT NAME FROM A AS A2 WHERE A2.ServiceReceived IN ('Special1', 'Special2'))
  

Комментарии:

1. Что такое здесь? если вы ссылаетесь на TableA, ваш запрос все еще выполняется.

2. Что такое «ВЫБРАТЬ ИМЯ ИЗ A КАК A2, ГДЕ A2.ServiceReceive» ????этот SQL неверен.

3. @SNash, я пересмотрел ответ Хаима, пытаясь сделать его более понятным.

4. @SNash, запрос работает отлично. Только Mr. A и Mr. C извлекают результирующий набор. Если вы хотите видеть различные значения, просто добавьте ОТДЕЛЬНОЕ предложение. И ‘A’ — это имя таблицы, точно так же, как это описано в вопросе «У нас есть таблица с именем A»