使用多个join sql查找多个计数

时间:2013-11-20 13:22:11

标签: mysql sql count left-join inner-join

我有四个表格,如

Destinations:
id , destination_name 

Activities:
id , destination_id

Attractions:
id , destination_id 

Fair :
id , destination_id

我正在使用

SELECT  d.id AS id, 
        d.destination_name AS destination_name,
        d.destination_type AS destination_type, 
        d.is_active AS is_active, 
        d.meta_description AS meta_description, 
        d.meta_keywords AS meta_keywords, 
        d.meta_title AS meta_title, 
        COUNT(att.id) AS attractions, 
        COUNT(act.id) AS activitys, 
        COUNT(f.destination_id) AS fairs 
FROM    destinations AS d 
        LEFT JOIN attractions AS att 
            ON d.id= att.destination_id 
        LEFT JOIN category_destination_ref AS act 
            ON d.id = act.destination_id 
        LEFT JOIN fairnfestival AS f 
            ON d.id = f.destination_id 
GROUP BY d.id 
ORDER BY d.id DESC 

但是它给了我“吸引力”和“展览会”coloumns的总和

1 个答案:

答案 0 :(得分:3)

你的问题是你加入了一个以上的1-n关系,所以用最简单的术语来说,如果你有两个景点和每个目的地的两个展览会,简单的加入将为你提供展览会和景点的笛卡尔产品:

DestinationID   FairID  AttractionID
1               1       1
1               1       2
1               2       1
1               2       2

正如您所看到的,FairID只有2个值,但是4行,因此计数将产生4,而不是您期望的2。

您需要使用COUNT(DISTINCT att.id) AS attractions,例如:

SELECT  d.id AS id, 
        d.destination_name AS destination_name,
        d.destination_type AS destination_type, 
        d.is_active AS is_active, 
        d.meta_description AS meta_description, 
        d.meta_keywords AS meta_keywords, 
        d.meta_title AS meta_title, 
        COUNT(DISTINCT att.id) AS attractions, 
        COUNT(DISTINCT act.id) AS activitys, 
        COUNT(DISTINCT f.id) AS fairs 
FROM    destinations AS d 
        LEFT JOIN attractions AS att 
            ON d.id= att.destination_id 
        LEFT JOIN category_destination_ref AS act 
            ON d.id = act.destination_id 
        LEFT JOIN fairnfestival AS f 
            ON d.id = f.destination_id 
GROUP BY d.id 
ORDER BY d.id DESC;

或将您的聚合移动到子查询:

SELECT  d.id AS id, 
        d.destination_name AS destination_name,
        d.destination_type AS destination_type, 
        d.is_active AS is_active, 
        d.meta_description AS meta_description, 
        d.meta_keywords AS meta_keywords, 
        d.meta_title AS meta_title, 
        COALESCE(att.attractions, 0) AS attractions, 
        COALESCE(act.activitys, 0) AS activities, 
        COALESCE(f.fairs, 0) AS fairs
FROM    destinations AS d 
        LEFT JOIN 
        (   SELECT  att.Destination_ID, COUNT(att.id) AS Attractions
            FROM    attractions AS att
            GROUP BY att.Destination_ID
        ) AS att 
            ON d.id = att.destination_id 
        LEFT JOIN 
        (   SELECT  act.Destination_ID, COUNT(act.id) AS activities
            FROM    category_destination_ref AS act
            GROUP BY act.Destination_ID
        ) AS act
            ON d.id = act.destination_id 
        LEFT JOIN 
        (   SELECT  f.Destination_ID, COUNT(f.id) AS fairs
            FROM    fairnfestival AS f
            GROUP BY f.Destination_ID
        ) AS f
            ON d.id = f.destination_id
ORDER BY d.id DESC;

我怀疑前者会在MySQL中表现更好,因为它不能很好地处理子查询,但如果你需要开始执行SUM,后者是必需的,因为SUM(DISTINCT将不起作用。