2013-07-16 63 views
0

我有一个mysql查询,从2个表'属性'和'提供'交互。MySQL的查询多JOIN两个表在多个列上

的“报价”表具有可以通过一个唯一的代码或由房产所在县或区域或者指的是特定记录匹配属性表中的记录。

这里是我的查询的例子...

SELECT *, ROUND(((3959 * acos(cos(radians(51.1080390)) * cos(radians(latitude)) * cos(radians(longitude) - radians(-4.1610140)) + sin(radians(51.1080390)) * sin(radians(latitude)))) * 2),0)/2 AS `distance` 
FROM `properties` AS prop 
LEFT JOIN `offers` ON prop.code = offers.the_property 
LEFT JOIN `offers` AS offsCnty ON prop.county = offsCnty.the_county 
LEFT JOIN `offers` AS offsRgn ON prop.region = offsRgn.the_region 
HAVING distance <= 2.5 
ORDER BY `sleeps` ASC, `distance` ASC 
LIMIT 0, 10 

在报价表中的3列the_property/the_county/the region是用于连接合适的报价与物业/ IES至关重要。如果要约要应用于整个县,则the_property字段为空,否则如果要约是针对特定属性的,则此字段包含唯一属性代码。

我认为通过使用多个JOIN将是解决方案,但是当三个主要的offer字段中的任何一个为空时,联接将为offers表字段返回“NULL”。

这怎么解决?

非常感谢

+1

'LEFT JOIN'意味着,如果没有行相匹配的'ON'条件,应该用'NULL'填充它。但只要它匹配3个连接中的一个,就应该在该组列中获得非空值。 – Barmar

回答

1

您可以加入两个表,并注明您的额外加入的加盟子句中条件或从更高版本提供表覆盖前面的条款

SELECT *, ROUND(((3959 * acos(cos(radians(51.1080390)) * cos(radians(latitude)) * cos(radians(longitude) - radians(-4.1610140)) + sin(radians(51.1080390)) * sin(radians(latitude)))) * 2),0)/2 AS `distance` 
FROM `properties` AS prop 
LEFT JOIN `offers` ON prop.code = offers.the_property 
     OR prop.county = offers.the_county 
     OR prop.region = offers.the_region 
HAVING distance <= 2.5 
ORDER BY `sleeps` ASC, `distance` ASC 
LIMIT 0, 10 
+0

我认为它应该是'OR',而不是'AND'。 – Barmar

+0

@Barmar哦再次感谢:) – DevZer0

+0

但我不确定这是否正确,因为它可以匹配'offers'中的多行,并且他只希望每个属性有一行。 – Barmar

0

列,你需要alias其中其中:

SELECT *,offers.the_property the_property_from_offers,...

0

你有三个个不同的提供所有具有相同字段名称的表格。问题是MySQL不允许具有相同名称的多个列。

最简单的解决方法是改变加入on子句中使用or

SELECT *, ROUND(((3959 * acos(cos(radians(51.1080390)) * cos(radians(latitude)) * cos(radians(longitude) - radians(-4.1610140)) + sin(radians(51.1080390)) * sin(radians(latitude)))) * 2),0)/2 AS `distance` 
FROM `properties` prop LEFT JOIN 
    `offers` 
     ON prop.code = offers.the_property or 
     (prop.county = offsCnty.the_county and offers.the_property is null) or 
     prop.region = offsRgn.the_region 
HAVING distance <= 2.5 
ORDER BY `sleeps` ASC, `distance` ASC 
LIMIT 0, 10; 

如果你使用多个连接,那么你应该有表达,如select子句中的以下内容:

select coalesce(offers.code, offsCnty.code, offsRgn.code) as code 

在报价表中的每一列。

+0

MySQL允许具有相同名称的多个列,它前缀与结果中的表别名。但是,PHP API放弃了前缀,因此您需要使用数字列索引来访问它们。 – Barmar

0

如果你想在最具体的报价优先,我想你必须把它写这样的:

SELECT prop.*, 
     COALESCE(offers.col1, offsCnty.col1, offsRgn.col1) col1, 
     COALESCE(offers.col2, offsCnty.col2, offsRgn.col2) col2, 
     ..., 
     <huge formula> distance 
FROM `properties` AS prop 
LEFT JOIN `offers` ON prop.code = offers.the_property 
LEFT JOIN `offers` AS offsCnty ON prop.county = offsCnty.the_county 
LEFT JOIN `offers` AS offsRgn ON prop.region = offsRgn.the_region 
HAVING distance <= 2.5 
ORDER BY `sleeps` ASC, `distance` ASC 
LIMIT 0, 10