【问题标题】:Getting results even if row doesn't exist in JOIN table即使 JOIN 表中不存在行也能获取结果
【发布时间】:2017-11-15 05:50:54
【问题描述】:

我存储了 2 种不同的备份类型(完整或日志),并且还有 2 种不同的服务器类型(本地或 Azure),下面的此查询将返回正确的结果,因为返回了 3 行,但是当我删除与此相对应的行时SQL 查询中的行:

AND (r4.Type = 'Full' AND r4.Server = 'Azure')

然后只检索 2 行,因为它们不是类型“完整”和服务器“Azure”的表中存在的行

这是我完成的查询:

SELECT DISTINCT
   r1.Tenant,
   r1.Name,
   r1.DBName,
   r1.Server as Server1,
   r1.Type as Type1,
   r1.Date as Date1,
   r2.Type as Type2,
   r2.Date as Date2,
   r2.Server as Server2,
   r3.Type as Type3,
   r3.Date as Date3,
   r3.Server as Server3,
   r4.Type as Typ4,
   r4.Date as Date4,
   r4.Server as Server4
FROM #Results AS r1
JOIN #Results AS r2 ON r2.DBName = r1.DBName 
JOIN #Results AS r3 ON r3.DBName = r1.DBName 
JOIN #Results AS r4 ON r4.DBName = r1.DBName 
WHERE
(r1.TYPE = 'Full' AND r1.Server = 'Local') AND
(r2.TYPE = 'Log' AND r2.Server = 'Local') AND
(r3.Type = 'Full' AND r3.Server = 'Azure') AND
(r4.Type = 'Log' AND r4.Server = 'Azure')
ORDER BY r1.Tenant

从上面的屏幕截图可以看出,这是检索到的数据。我希望另一行包含以下内容:

  • 日志,本地
  • 完整,本地
  • 日志,Azure
  • NULL、NULL(因为不存在完整的 Azure 备份)

这是 Result 表中的数据:

【问题讨论】:

  • 请改用LEFT JOIN。添加示例数据和预期输出,以便我们提供更详细的答案
  • @JuanCarlosOropeza 即使这样也行不通。仍然只检索到 2 个结果
  • 正如我所说,向我们展示示例数据和预期输出。
  • @JuanCarlosOropeza 添加了示例数据
  • 你只包括欲望输出。请添加源数据。就像让魔术师在没有正确设置的情况下做魔术一样。

标签: mysql azure


【解决方案1】:

您将需要使用LEFT JOIN,因为当 r3 和 r4 为空时,您仍然需要 r1 和 r2 的结果行。

您可能尝试修改所有JOIN 状态,但得到了相同的结果...问题出在这里。当你尝试时:

SELECT * FROM table_1 t1
LEFT JOIN table_2 t2 ON t1.id = t2.t1_id
WHERE t2.some_column = 'a value'

LEFT JOIN 工作正常,并返回具有空 t2 值的行,但是该行在 WHERE 子句中被丢弃。 t2.some_column = 'a value' 不可能是真的,因为 t2.some_column = NULL

解决方案:

SELECT * FROM table_1 t1
LEFT JOIN table_2 t2 ON t1.id = t2.t1_id AND t2.some_column = 'a value'

现在任何没有 `some_column = 'a value' 的 t2 行都不会包含在结果集中,但这没关系,因为我们使用的是 LEFT JOIN,因此该行将包含 t1 值和 NULL t2 值

您也可以尝试:WHERE t2.is IS NULL OR t2.some_column = 'a value'

关于您的查询:

```select ... 
FROM #Results AS r1 
LEFT JOIN #Results AS r2 ON r2.DBName = r1.DBName AND (r2.TYPE = 'Log' AND r2.Server = 'Local') 
LEFT JOIN #Results AS r3 ON r3.DBName = r1.DBName AND (r3.Type = 'Full' AND r3.Server = 'Azure') 
LEFT JOIN #Results AS r4 ON r4.DBName = r1.DBName AND (r4.Type = 'Log' AND r4.Server = 'Azure') 
WHERE (r1.TYPE = 'Full' AND r1.Server = 'Local') 
ORDER BY r1.Tenant```

【讨论】:

  • 你能写一个与我的查询相对应的查询吗?因为我刚刚尝试过,它几乎可以工作,但只返回本地行的完整备份
  • 添加了对答案的更新。请注意,我假设 r1 中的任何列都不会为空
  • 谢谢!什么 r1、r2 和 r3 可以为空?我是否必须按照您采取的相同程序进行操作?
  • 老实说,当我第一次回答时,我并没有真正注意到您在一张桌子上进行所有这些连接......我可能会选择@JuanCarlosOropeza 发布的答案
【解决方案2】:
 SELECT Tenant,  Name, DBName,
        MAX( CASE WHEN Server = 'local' and Type = 'full'
                  THEN Date END) as FullLocalDate,
        MAX( CASE WHEN Server = 'local' and Type = 'log'
                  THEN Date END) as LogLocalDate,
        MAX( CASE WHEN Server = 'azure' and Type = 'full'
                  THEN Date END) as FullAzureDate,
        MAX( CASE WHEN Server = 'azure' and Type = 'log'
                  THEN Date END) as LogAzureDate
 FROM #Results r
 GROUP BY Tenant,  Name, DBName

我删除列 Server1 Server2 ... 因为已经是日期信息的一部分。但如果需要可以添加。

【讨论】:

  • 你试过了吗?有cmets吗?
猜你喜欢
  • 2011-08-20
  • 2019-08-20
  • 2021-01-30
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 2013-10-14
  • 1970-01-01
相关资源
最近更新 更多