MySQL - 通过连接具有多个WHERE / OR子句的多个表来返回单个记录

时间:2016-12-02 10:54:28

标签: mysql left-join inner-join

进行了多次搜索并能够编写除此之外的所有JOIN查询。我有3个表,看起来像:

TABLE - accounts
account_id | account_email
1          | aa@bb.com
2          | cc@dd.com

TABLE - products
product_id | product_name
1          | name1
2          | name2

TABLE - licenses
license_id | account_id | product_id | license_code
1          | 1          | 1          |
2          | 1          | 2          |
3          | 0          | 1          | abc123

我知道account_emailproduct_idlicense_code(这可能是空的)变量,需要检查客户是否拥有所选产品的许可(按account_email搜索或license_code)。

问题是account_id有时可能为0(换句话说,客户端有许可证,但客户端的配置文件未存储在帐户表中)。

尝试使用这个,但它返回错误的(重复的)结果:

SELECT * FROM licenses 
INNER JOIN products ON licenses.product_id=products.product_id AND products.product_id='X' 
INNER JOIN accounts ON licenses.account_id=accounts.account_id AND accounts.account_email='XYZ' OR licenses.license_code='ZZZ'

问题:如何重写查询,以便我可以在account_emaillicense_code字段找到记录?简而言之,如果account_id不是0(配置文件存在),我应该看到3个表(帐户,产品,许可证)中的数据。如果account_id为0,我应该看到来自2个表的数据(来自accounts表的值应该显示为空/ null)。

毋庸置疑,account_emaillicense_code字段是唯一的。

2 个答案:

答案 0 :(得分:0)

您只需要调整括号即可。但是,我会使用单独的WHERE子句:

SELECT *
FROM licenses l INNER JOIN
     products p
     ON l.product_id = p.product_id INNER JOIN
     accounts a
     ON l.account_id = a.account_id
WHERE p.product_id = 'X' AND
      (a.account_email='XYZ' OR l.license_code = 'ZZZ')

您可以将过滤器保留在ON子句中 - 这没有任何问题。我只想将连接条件与过滤条件分开。重要的部分是括号,因此ON子句不被解释为:

ON (l.account_id = a.account_id AND a.account_email = 'XYZ') OR
  licenses.license_code = 'ZZZ'

这是没有parens的解释。

答案 1 :(得分:0)

经过一些代码修改和测试后,这里的代码完美无缺。它是一个经过修改的Gordon Linoff代码(当只知道license_code时,原始代码不起作用,并且电子邮件地址不为人所知)。所以大部分学分归功于戈登·林诺夫的努力。

SELECT *
FROM licenses l JOIN
     products p
     ON l.product_id = p.product_id LEFT JOIN
     accounts a
     ON l.account_id = a.account_id
WHERE p.product_id = 'X' AND
      (a.account_email='XYZ' OR l.license_code = 'ZZZ')