#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
Я пытаюсь получить список идентификаторов обратно из запроса, который зависит от значения в столбце ссылки на идентификатор и столбце даты в другой строке.
В принципе, я пытаюсь получить ID
для записей, которые были созданы до указанной даты ( Created
столбец), если на эту запись не ссылается другая (по RefID
столбцу), созданная после этой даты.
(Я планирую использовать это в sproc в какой-то момент, но пока просто использую переменную)
Очень простой пример таблицы ниже. Для простоты исключены несвязанные столбцы.
-------- --------- ---------------
| ID | RefID | Created |
-------- --------- ---------------
| 123 | NULL | 2016-10-18 |
| 456 | 123 | 2016-10-20 |
| 789 | NULL | 2016-10-18 |
| 111 | 789 | 2016-10-18 |
-------- --------- ---------------
Итак, в моем примере таблицы выше, если бы я указал 2016-10-19, я бы вернул идентификаторы 789 и 111. Я бы не получил 123, потому что, хотя он был создан до 2016-10-18, на него ссылается 456, чего не было (поэтому я бы также не вернул 456).
Я перебирал варианты присоединения, но SQL определенно не моя сильная сторона, поэтому я чувствую, что бегаю по кругу и гоняюсь за неправильным решением при этом!
Пока у меня есть это, что, я думаю, дает мне правильный список идентификаторов, на которые ссылаются после определенной даты. Я не совсем уверен, как исключить этот список из моего основного запроса…не говоря уже о том, каким был бы соответствующий основной запрос.
DECLARE @myDate datetime
SET @myDate = '2016-10-19'
SELECT t1.id
FROM MyDB.dbo.[myTable] AS t1
JOIN MyDB.dbo.[myTable] AS t2
ON t1.id = t2.ref_id
WHERE t1.id = t2.ref_id AND t2.created > @myDate
Ответ №1:
Вы можете получить это с помощью not exists
с условием проверить, есть ли в указанном идентификаторе строка после указанной даты.
SELECT id
FROM MyDB.dbo.[myTable] t1
WHERE NOT EXISTS (SELECT 1 FROM MyDB.dbo.[myTable]
WHERE t1.id = ref_id
AND created > @myDate)
AND created < @myDate
Комментарии:
1. Смогу ли я расширить это, чтобы рассмотреть 2 разные даты? Скажите, если бы я хотел, чтобы идентификаторы были до даты [X], и если на них были ссылки, ссылка должна быть создана до даты [Y]?
2. конечно.. вы можете это сделать.
3. Извините, просто удостоверяюсь, прежде чем начать слепо вводить значения для тестирования. Будет ли это просто переменной using [X] для
@myDate
в строке 6 и новой переменной [Y] в@myDate
строке 5?4. да, внутреннее условие проверяет, имеет ли какой-либо из ref_id более позднюю дату, а внешним условием является идентификатор, предшествующий заданной дате. вы можете соответствующим образом изменить его.
Ответ №2:
ОТРЕДАКТИРОВАНО: я понял (после принятого решения и повторного прочтения исходного запроса), что вы просили исключить записи t1, которые имели связанные записи t2 после создания t1, но после даты «mydate». Я соответствующим образом изменил свои запросы ниже (однако я предполагаю, что запрос vkp также работает лучше, чем мой пересмотренный ответ).
Я начал с вашего запроса и пришел к этому предложению:
SELECT t1.id
FROM MyDB.dbo.[myTable] AS t1
LEFT JOIN MyDB.dbo.[myTable] AS t2
ON t1.id = t2.ref_id and t2.created > @mydate
WHERE t2.id is null AND t1.created < @mydate
Итак, для таблицы t1 (до указанной даты) я объединяю (если они существуют) все обращения с датой создания, большей, чем «mydate», а ref_id равен t1.id.
После этого я говорю, что мне не нужны строки, в которых я нашел совпадение (это использование t2.id is null
), таким образом, оставляя меня с желаемым набором результатов.
Что касается последнего добавления к запросу (имеющего другую «начальную дату» для ссылки в записях для исключения), вам просто нужно будет изменить запрос следующим образом:
SELECT t1.id
FROM MyDB.dbo.[myTable] AS t1
LEFT JOIN MyDB.dbo.[myTable] AS t2
ON t1.id = t2.ref_id
and t2.created > @exclusionstartdate
WHERE t2.id is null AND t1.created < @mydate