2017-10-12 91 views
-1

我有以下3个表:LEFT JOIN的(也许)功能,双连接查询的WHERE

Clients AS c 
-------- 
ClientID, 
ClientGUID, 
InitializationDate, 
LastCheckin 

ClientServices AS cs 
--------------- 
ClientID, 
ServiceID, 
Status, 
Version 

Services AS s 
--------- 
ServiceID, 
Name, 
Description 

我需要建立一个查询,这将使我的结果如下:

s.Name, cs.Version 

我需要它充当左连接,因为我希望显示所有服务,而不管该服务是否在ClientServices中。在这种情况下,所选版本将简单显示为NULL

我尝试做一些简单的连接,但是我使用的每个组合LEFT JOINJOIN都只会导致属于该客户端的ClientServices出现。举个例子:

SELECT s.`Name`, 
      cs.`Version` 
FROM  `Services` s LEFT JOIN ClientServices cs ON 
      s.`ServiceID` = cs.`ServiceID` 
      JOIN Clients c ON 
      cs.`ClientID` = c.`ClientID` 
WHERE  `ClientGUID`='thisisanewguid' 

我能够最终与此查询得到期望的结果:

SELECT s.`Name`, 
      cs.`Version` 
FROM  `Services` s LEFT JOIN ClientServices cs 
      ON s.`ServiceID` = cs.`ServiceID` 
WHERE  cs.ClientID = (
          SELECT ClientID 
          FROM  Clients 
          WHERE  ClientGUID='thisisanewguid' 
         ) 
OR  cs.ClientID IS NULL 

,但我觉得好像它有点“哈克”。有没有更好的方法来获得相同的结果集,但没有在一个查询中执行多个选择? (优选仅加入,但我不知道如果多数民众赞成可能的了)

示例数据集中:

客户:

ClientID,   ClientGUID, InitializationDate, LastCheckin 
     1, 'xxxxxxxxxxxxxxxx',   10/10/2017, 10/12/2017 
     2, 'thisisanewguid',   05/23/2017, 10/12/2017 

ClientServices:

ClientID, ServiceID, Status, Version 
     1,   1,  1, '0.1' 
     2,   1,  1, '0.1' 
     2,   2,  1, '0.2' 

服务:

ServiceID,  Name,        Description 
     1, InITManager, 'Manages and updates all InIT services.' 
     2,  InITIAM,  'InIT's Inventory/Asset Management.' 
     3, InITTesting,        'testing' 

所需的结果集WHERE ClientGUID = 'thisisanewguid':

 Name, Version 
InITManager, '0.1' 
    InITIAM, '0.2' 
InITTesting, NULL 
+0

请参阅https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very -simple-sql-query – Strawberry

+0

如果未找到任何结果,则左连接会生成null,如果未找到任何记录,则内连接会删除该行。你从表的左边开始连接到cs ..所以cs null是有效的,你会看到s的结果,在这一点上没有对应的cs入口。然后你从cs内部连接到c ...第一个左连接留下的所有空值现在在此连接处被过滤掉。合理?左连接后跟内连接就是自我挫败。 – Twelfth

+0

这是有道理的,我确实没有想到它,但是当我继续尝试两个'LEFT JOIN'时,它仍然不起作用,因为我必须指定'WHERE c.ClientGUID ='thisisanewguid''。事实上,我越想到它,我越倾向于认为我的第二个查询是唯一的方法。 – TheEggSample

回答

2

为obatin您显示结果在问题你可以使用左表左连接没有where子句列涉及ID左加入

SELECT s.`Name`, 
      cs.`Version` 
FROM  `Services` s 
LEFT JOIN ClientServices cs ON s.`ServiceID` = cs.`ServiceID` 
LEFT JOIN Clients c ON c.ClientID = cs.ClientID AND c.`ClientGUID`='thisisanewguid' 
+0

有了这个,我没有办法指定'WHERE ClientGUID ='thisisanewguid'' – TheEggSample

+0

答案更新..对于客户端加入 – scaisEdge

+0

谢谢!我从来没有想过或知道你可以在JOIN中使用'AND'。再次感谢。 – TheEggSample

0

嗨能否请您尝试以下查询

SELECT cs.Version, s.Name 
FROM ClientServices cs 
RIGHT JOIN Clients c ON c.ClientID = cs.ClientID 
RIGHT JOIN Services s ON s.ServiceID = cs.ServiceID 
+0

这几乎有我正在寻找的功能......但如果我添加'WHERE c.ClientGUID ='thisisanewguid',那么我只能得到InITManager和InITIAM。 – TheEggSample