此相关子查询的更高效版本

时间:2013-02-10 10:01:10

标签: mysql sql subquery correlated-subquery

我有3个不同的表,我需要从2个中提取一次数据,从第3个中提取两次。表格为jobscustomerscustomers_attributes。我正在尝试为特定作业提取数据,而部分数据是有关拥有该作业的客户的信息。客户数据存储在customers_attributes中,其中数据类型定义为与类型对应的整数(为简单起见,此处使用字符串),然后内容字段包含数据本身。

在这种情况下,我需要从customers_attributes表中提取对应于与作业对应的客户的2行。 “PhoneNumber”为一行,“CustomerInfo”为另一行。我为其中一个使用了INNER JOIN,但因为我不能为两者都设置WHERE值,所以我使用了另一个子查询。我认为这真的很讨厌,我确信必须采用更清洁的方式:

SELECT jobs.*, customers.Name AS CustomerName,
       customers_attributes.Content AS PhoneNumber,
       (     SELECT `Content`
             FROM customers_attributes
             WHERE Type = 'CustomerInfo' AND ForeignCustomer = jobs.Customer
             LIMIT 1) AS CustomerInfo
FROM jobs
INNER JOIN customers ON jobs.Customer = customers.ID
INNER JOIN customers_attributes ON jobs.Customer = customers_attributes.ForeignCustomer
WHERE jobs.ID = $jobID AND customers_attributes.Type = 'PhoneNumber'
LIMIT 1

我应该提一下,如果客户有多个作业,那么客户可以为同一属性设置多行,理想情况下,此查询应该返回最新信息,或者与作业同时提交的信息(基于相应的ID订单)。

1 个答案:

答案 0 :(得分:1)

只需在另一个别名下再次加入同一个表。

SELECT j.*, c.Name AS CustomerName,
       ca.Content AS PhoneNumber,
       ca2.Content as CustomerInfo
FROM jobs j
INNER JOIN customers c ON j.Customer = c.ID
INNER JOIN customers_attributes ca ON (j.Customer = ca.ForeignCustomer)
INNER JOIN customers_attributes ca2 ON (j.Customer = ca2.ForeignCustomer)
WHERE j.ID = '$jobID' 
  AND ca.Type = 'PhoneNumber'
  AND ca2.Type = 'CustomerInfo'
LIMIT 1

警告
看起来你正在使用PHP。如果您必须坚持使用过时的mysql_库,而不是使用经过充分改进的mysqli_库。 请记住使用mysql_real_escape_string()并引用您的$vars 如果没有,你会被SQL注入问题隐藏起来。