SQL — Объединить 2 таблицы, используя объединенный столбец И условие

#sql #sql-server #sql-server-2008 #left-join #sqlfiddle

#sql #sql-сервер #sql-сервер-2008 #левое соединение #sqlfiddle

Вопрос:

У меня есть очень простой запрос для SQL Server 2008, но я не могу добиться успеха в достижении того, чего я хочу.

Объяснение
У меня есть следующая схема :

Схема SQL

Для заданного 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. Вы правы, и я сожалею, что в одной строке были неверные данные. Я исправил это. Однако «Должно появиться» — это всего лишь визуальная проверка, чтобы проверить, возвращает ли запрос правильные строки, предложение, В КОТОРОМ текст комментария В (…) — это не то, что я ищу, вы догадываетесь, что у меня не было таких значений в моей реальной базе данных