#sql #sql-server #sql-server-2008 #left-join #sqlfiddle
#sql #sql-сервер #sql-сервер-2008 #левое соединение #sqlfiddle
Вопрос:
У меня есть очень простой запрос для SQL Server 2008, но я не могу добиться успеха в достижении того, чего я хочу.
Объяснение
У меня есть следующая схема :
Для заданного FAVORITE
у пользователя может быть ноль или много COMMENTs
, однако, если у пользователя более одного комментария, у всех COMMENTs
есть a DeletedDate
NOT NULL
(кроме, возможно, последнего).
DeletedDate
действует как флаг «IsDeleted», приложение гарантирует, что только ноль или один комментарий для каждого пользователя на избранное NULL
. Если DeletedDate
это NULL
так, запись считается удаленной.
Но у пользователя может быть FAVORITE
без COMMENT
. COMMENT
является полностью необязательным.
Что бы я хотел
Я пытаюсь создать запрос, который для данного пользователя вернет все его действительные избранные (где FAVORITE.DeleteDate
есть NOT NULL
) и действительный COMMENT
, связанный с FAVORITED
(если он существует).
Вот мой запрос :
SELECT *
FROM FAVORITE f
LEFT JOIN COMMENT co ON f.IdReferenced = co.IdReferenced
WHERE f.IdUser = 7
AND f.DeletedDate IS NULL
AND co.IdUser = 7
(Пожалуйста, используйте idUser = 7 для тестирования)
Однако этот запрос возвращает все COMMENTs
FAVORITEs
данные пользователя 7, даже комментарии, где DeletedDate
НЕ равно NULL.
Я попытался добавить a AND co.DeletedDate IS NOT NULL
к приведенному выше запросу, но теперь он не вернул избранное, у которого нет комментариев
СКРИПКА
Чтобы воспроизвести проблему, я создал этот SQLFIDDLE
РЕЗУЛЬТАТЫ ПОПЫТКИ
Если я не был ясен в своих объяснениях, запрос должен вернуть ЧЕТЫРЕ строки моего SQLFIDDLE, где поле commentText «Должно появиться 1», «Должно появиться 2», «Должно появиться 3», «Должно появиться 4»
Запрос должен возвращать указанные выше строки за вычетом перечеркнутой красным строки
ВАЖНО, я только что допустил ошибку в моем SQLFIDDLE, четвертая строка комментария должна быть
INSERT [dbo].[COMMENT] ([IdComment], [IdUser], [IdReferenced], [CommentText], [CreationDate], [ModificationDate], [DeletedDate]) VALUES (8, 7, 2869, N'Must appear 3', CAST(0x0000A33500EC1133 AS DateTime), NULL, NULL)
Не могли бы вы улучшить мой запрос? Мне придется написать это в LINQ, но я должен быть в состоянии перейти от SQL к LINQ.
Спасибо за ваше время!
Комментарии:
1. Переместите все ссылки на co из предложения WHERE в условие ОБЪЕДИНЕНИЯ. Без этого вы, по сути, «превращаете» ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ во ВНУТРЕННЕЕ условие соединения.
2. Почему должно отображаться «Должно отображаться 3»?
3. Пожалуйста, проверьте свой sqlfiddle, поскольку данные кажутся недопустимыми
4. Хорошо, мне очень жаль, что вы правы, «Должно появиться 3» должно иметь DeletedDate = NULL, однако я копирую / вставляю datetime, поэтому это не null — моя скрипка. Полностью извините. Я проверю ваши ответы 🙂
Ответ №1:
Если я понимаю ваше требование, вам нужно указать условие для правильной таблицы ( co.DeletedDate IS NOT NULL
) в JOIN
части вашего запроса, например:
SELECT *
FROM FAVORITE f
INNER JOIN COMMENT co ON f.IdReferenced = co.IdReferenced
AND co.DeletedDate IS NULL
AND co.IdUser = f.IdUser
WHERE f.IdUser = 7
AND f.DeletedDate IS NULL
Редактировать:
В вашей скрипке sql в строке ниже было вставлено значение в DeletedDate. Если это значение null
указано выше, запрос дает желаемый результат. Также изменили значение « LEFT JOIN
на» INNER JOIN
, чтобы не показывать разных пользователей.
INSERT [dbo].[COMMENT] ([IdComment], [IdUser], [IdReferenced], [CommentText], [CreationDate], [ModificationDate], [DeletedDate]) VALUES (8, 7, 2869, N'Must appear 3', CAST(0x0000A33500EC1133 AS DateTime), NULL, NULL)
Комментарии:
1. Я допустил ошибку в своих данных в sqlfiddle, мне очень жаль за это. Я только что исправил данные, но когда я выполняю ваш запрос, у меня на выходе только две строки, тогда как у меня могло быть 4 (четыре с текстом комментария «должны появиться»). Этот текст комментария здесь только для проверки выходных данных, решение, в КОТОРОМ текст комментария В (…), очевидно, не я ищу
2. @AlexB, пожалуйста, проверьте еще раз, так как я допустил ошибку при вставке. в основном там
co.DeletedDate IS NOT NULL
, где должно бытьco.DeletedDate IS NULL
3. Кажется, у нас есть победитель 🙂 Большое вам спасибо!
Ответ №2:
Если я правильно понял вашу проблему. Вы могли бы использовать EXISTS
для проверки, существует ли такая запись SQLFiddle
SELECT *
FROM FAVORITE f
LEFT JOIN COMMENT co ON f.IdReferenced = co.IdReferenced
WHERE f.IdUser = 7
AND f.DeletedDate IS NULL
AND EXISTS ( SELECT 1 FROM COMMENT WHERE COMMENT.IdUser = co.IdUser AND co.DeletedDate IS NULL)
Комментарии:
1. Я, вероятно, был не очень ясен, и я прошу прощения за это. Пожалуйста, взгляните на раздел «Результат попытки» моего первого сообщения, которое я только что обновил. Я пытался использовать ваше предложение EXISTS, но безуспешно
Ответ №3:
Этот запрос вернет все записи из избранной таблицы, независимо от того, есть ли соответствующий комментарий или нет (левое соединение) и где f.DeletedDate is not null
И где c.CommentText in (values)
Select * from favorite f
left join comment c on c.IdReferenced = f.IdReferenced
and f.DeletedDate is null
where c.CommentText in ('Must appear 1', 'Must appear 2','Must appear 3','Must appear 4')
and f.IdUser = 7
--can use an OR statement as well
Комментарии:
1. Хотя этот блок кода может ответить на вопрос, было бы лучше, если бы вы могли дать небольшое объяснение, почему он это делает.
2. Это не так. Я, вероятно, не очень ясно выразился, извините. Пожалуйста, ознакомьтесь с моим обновленным сообщением, раздел «Результаты попыток»
3. Похоже, вам нужны все записи, где
f.DeletedDate is null
, но это не то, что вы сказали в вопросе4. Вы правы, и я сожалею, что в одной строке были неверные данные. Я исправил это. Однако «Должно появиться» — это всего лишь визуальная проверка, чтобы проверить, возвращает ли запрос правильные строки, предложение, В КОТОРОМ текст комментария В (…) — это не то, что я ищу, вы догадываетесь, что у меня не было таких значений в моей реальной базе данных