【问题标题】:SQL - Join 2 tables using a join column AND a conditionSQL - 使用连接列和条件连接 2 个表
【发布时间】:2014-06-24 12:47:53
【问题描述】:

我对 SQL Server 2008 有一个非常简单的请求,但我无法成功实现我想要的。

说明 我有以下架构:

对于给定的FAVORITE,一个用户可以有零个或多个COMMENTs,但是,如果用户有多个评论,则所有COMMENTs 都有一个DeletedDate NOT NULL(可能最后一个除外).

DeletedDate 充当标志“IsDeleted”,应用程序确保每个用户每个收藏夹只有零或一条评论是NULL。如果DeletedDateNULL,则认为该记录已删除。

但用户可以拥有FAVORITE 而没有COMMENTCOMMENT 是完全可选的。

我想要什么


我正在尝试创建一个请求,对于给定用户,该请求将返回其所有有效的收藏夹(其中FAVORITE.DeleteDateNOT NULL)和与FAVORITED 关联的有效COMMENT(如果它存在)。

这是我的要求:

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进行测试)

但是,此请求返回用户 7 的所有 FAVORITEs 中的所有 COMMENTs,甚至包括 DeletedDate 不为 NULL 的 cmets。

我尝试在上述请求中添加AND co.DeletedDate IS NOT NULL,但现在它没有返回没有任何评论的 FAVORITEs


小提琴


为了重现问题,我创建了这个SQLFIDDLE



尝试的结果


如果我的解释不清楚,请求必须返回我的 SQLFIDDLE 的四行,其中 CommentText 字段是“必须出现 1”、“必须出现 2”、“必须出现 3”、“必须出现 4”

请求必须返回上述行,减去红叉线

重要 我刚刚在我的 SQLFIDDLE 中出错了,COMMENT 的第四行应该是

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。
感谢您的宝贵时间!

【问题讨论】:

  • 将所有对 co 的引用移出 WHERE 子句并进入 JOIN 条件。如果没有这个,您实际上是在将 LEFT OUTER JOIN “制作”为 INNER JOIN 条件。
  • 为什么要显示“必须出现3”?
  • 请检查您的 sqlfiddle,因为数据似乎无效
  • 好吧,我真的很抱歉你是对的,“Must Appear3”必须有 DeletedDate = NULL,但是我复制/粘贴了一个日期时间,所以它不是 null 是我的小提琴。完全对不起。我会检查你的答案:-)

标签: sql sql-server sql-server-2008 left-join sqlfiddle


【解决方案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 fiddle 中,下面的行在 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)

【讨论】:

  • 我在 sqlfiddle 上的数据出错了,对此我感到非常抱歉。我刚刚更正了数据,但是当我执行您的请求时,输出中只有两行,而我可以有 4 行(带有注释文本“必须出现”的四行)。这个评论文本只是在这里验证输出,一个解决方案 WHERE CommentText IN (...) 显然不是我要找的
  • @AlexB,请再次检查,因为我粘贴时出错了。基本上有co.DeletedDate IS NOT NULL应该是co.DeletedDate IS NULL
  • 看来我们赢了 :-) 非常感谢!
【解决方案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)

【讨论】:

  • 我可能不是很清楚,对此我很抱歉。请查看我刚刚更新的第一篇文章的“尝试结果”部分。我尝试使用您的 EXISTS 子句,但没有成功
【解决方案3】:

此查询将返回收藏夹表中的所有记录,无论是否有匹配的评论(左连接)以及f.DeletedDate is not nullc.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

【讨论】:

  • 虽然这个代码块可能会回答这个问题,但最好能稍微解释一下为什么会这样。
  • 它没有。我可能不是很清楚,对不起。请查看我更新的帖子,“尝试的结果”部分
  • 看起来你想要f.DeletedDate is null 的所有记录,但这不是你在问题中所说的
  • 你是对的,很抱歉,一行有无效数据。我纠正了它。但是,“必须出现”只是一个视觉检查,以验证请求是否返回好的行,一个子句 WHERE CommentText IN (...) 不是我要找的,你猜我没有这样的值我的真实数据库
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多