#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»