#sql #sql-server
#sql #sql-сервер
Вопрос:
Я новичок в SQL Server. Мне нужно отфильтровать запрос, но я не уверен, как. В моем запросе есть соединения, которые я опустил здесь для простоты.
SELECT Name, Date
FROM my_table AS C
WHERE Date = '2019-04-15' AND Date IS NULL
В My_table есть такие данные:
Name Date
---------------------
John 2019-04-01
Ally 2019-04-01
Steve NULL
James 2019-04-15
James NULL
Если я выполняю запрос для любого из условий where, я получаю ожидаемые результаты только для одного условия. Но добавление И не дает результатов. Использование ИЛИ дает мне последние 3 записи. Но то, что я ищу, это отфильтровать его, чтобы я просто видел последние 2 записи, поскольку у Джеймса есть запись, которая соответствует дате, а также запись с НУЛЕВОЙ датой.
Как я могу отфильтровать имена, которые соответствуют ОБОИМ условиям? Заранее спасибо.
Комментарии:
1. Вероятно, вы хотите
OR
, неAND
:Date = '2019-04-15' OR Date IS NULL
2. «Использование ИЛИ дает мне последние 3 записи. Но то, что я ищу, это отфильтровать его, чтобы я просто видел последние 2 записи, поскольку у Джеймса есть запись, которая соответствует дате, а также запись с нулевой датой.»
3. Итак, вам нужны только строки для James? Почему вы не фильтруете с помощью WHERE name = ‘James’
4. ForpasI — t не всегда является Джеймсом, которого я ищу. Я ищу все имена, в которых есть строка с определенной датой, и строку с тем же именем с НУЛЕВОЙ датой.
5. И почему вы не упомянули об этом в своем вопросе?
Ответ №1:
Вы могли бы попробовать это:
SELECT a.name
FROM my_table a
JOIN my_table b
ON a.name = b.name
AND b.date IS NULL
WHERE a.date = '2019-04-15';
Конечно, если существует несколько записей для определенного имени с NULL
датой, вы получаете несколько результатов.
Это можно решить следующим образом:
SELECT a.name
FROM my_table a
WHERE a.date = '2019-04-15'
AND EXISTS (SELECT *
FROM my_table b
WHERE a.name = b.name
AND b.date IS NULL);
Ответ №2:
Из ваших комментариев:
Я ищу все имена, в которых есть строка с определенной датой, и строку с тем же именем с НУЛЕВОЙ датой
Вы можете сделать это с помощью EXISTS:
select name
from my_table t
where
date = '2019-04-15'
and exists (
select 1 from my_table
where name = t.name and date is null
)
Редактировать
Если вам нужны как строка с ненулевой датой, так и строка с нулевой датой:
select t.*
from my_table t
where (
date = '2019-04-15'
and exists (
select 1 from my_table
where name = t.name and date is null
)
) or (
date is null
and exists (
select 1 from my_table
where name = t.name and date = '2019-04-15'
)
)
Смотрите демонстрацию
Комментарии:
1. Я пытаюсь это сделать. Мне просто нужно выяснить, как обернуть его с помощью имеющихся у меня объединений.
2. Наконец-то появилось время попробовать это. Я не знал о предложении EXISTS . После попытки я получаю только даты 4/15 и, похоже, игнорирую условие NULL. У меня есть соединения с обоими операторами select. Оба предложения where независимо выдают мне соответствующие отфильтрованные результаты. Но EXISTS ничего не делает для изменения результатов из первого предложения WHERE. Я подозреваю, что это как-то связано с тем, как я внедряю ваше решение. Я продолжу работать с ним.
3. Попробуйте обернуть свой запрос (без моего кода) внутри CTE и применить мой код к cte, например:
with cte as (<your query>) select distinct name from cte t where date is not null and exists (select 1 from cte where name = t.name and date is null )
4. Извините, что так долго возвращаюсь к этому. Итак, я вложил свой запрос в ваш cte. Результаты представляют собой список уникальных имен с датой 4/15. Имена с нулевым значением исключаются. (Я изменил свой исходный опубликованный запрос, чтобы использовать AND вместо OR.)
5. Итак, вам нужны также строки со значением pair null, верно?
Ответ №3:
Попробуйте это:
SELECT
Name,
Date,
COUNT(C.Date)
FROM my_table AS C
having COUNT(C.Date) > 1
group by
Name,
Date
Ответ №4:
SELECT
Name,
Date,
COUNT(temp.Date)
FROM my_table AS temp
where temp.Date = '2019-04-15' OR temp.Date IS NULL
having COUNT(temp.Date) > 1
group by
Name,
Date
Ответ №5:
Если вам нужна строка, которая также имеет нулевое значение, вы можете попробовать ниже.
SELECT m.name,m.Date
FROM my_table m
WHERE (m.date = '2019-04-15' OR m.date IS NULL
AND EXISTS (SELECT 1
FROM my_table im
WHERE m.name = im.name
AND im.date IS NOT NULL))
Этого также можно достичь с помощью SELF JOIN.
SELECT DISTINCT m.name,m.Date
FROM my_table m
INNER JOIN my_table im ON im.Name = m.Name
WHERE (m.date = '2019-04-15' OR m.date IS NULL
AND im.Date IS NOT NULL)
Комментарии:
1. Я пробовал варианты EXIST с другими ответами, но безрезультатно. Ваш немного отличается, ваш выдает мне список всех имен с нулевой датой и всех имен с датой, мало чем отличающийся от простого добавления DISTINCT в первую строку SELECT. Если я понимаю предложение EXiSTS , оно гласит «Дайте мне имена и записи 4/15, а теперь покажите мне, какие из них в этом результате не являются нулевыми?» Это почти так, как будто мне нужно выполнить 2 запроса, а затем третий, чтобы сопоставить имена, найденные в обоих.
2. Да, он говорит, дайте мне имена и даты, где date = ‘2019-04-15’ или date равно null, а затем снова просмотрите таблицу, чтобы увидеть, совпадает ли имя с выбранными строками.