【问题标题】:MySQL multiple Left Joins causing incorrect Count valuesMySQL 多个左连接导致不正确的计数值
【发布时间】:2012-06-15 17:17:47
【问题描述】:

所以我正在尝试编写一个 MySQL 查询来用三个单独的查询替换当前在 PHP 中所做的事情。我有一个只有两个值的类别表:一个 ID 和一个名称。还有另外两个表,每个表都有一个外键引用第一个表中的 ID。我需要从 Categories 表中获取所有值的列表,以及在其他两个表中每个值被引用的次数的计数。我可以使用单独的查询从每个第二个表中准确地获取计数:

SELECT nga_calevir_event_categories.*, COUNT(nga_calevir_events.event_id) AS event_total
FROM nga_calevir_event_categories
LEFT JOIN (nga_calevir_events)
ON nga_calevir_event_categories.id = nga_calevir_events.event_category
GROUP BY nga_calevir_event_categories.id;

SELECT nga_calevir_event_categories.*, COUNT(nga_usermeta.user_id) AS member_total
FROM nga_calevir_event_categories
LEFT JOIN (nga_usermeta)
ON (nga_usermeta.meta_value = nga_calevir_event_categories.id
AND nga_usermeta.meta_key = 'category_id')
GROUP BY nga_calevir_event_categories.id;

但是,当我尝试组合这些查询时,它开始为这两个计数提供不正确的结果。这是组合查询:

SELECT nga_calevir_event_categories.*,
COUNT(nga_calevir_events.event_id) AS event_total,
COUNT(nga_usermeta.user_id) AS member_total
FROM nga_calevir_event_categories
LEFT JOIN (nga_calevir_events)
ON nga_calevir_event_categories.id = nga_calevir_events.event_category
LEFT JOIN (nga_usermeta)
ON (nga_usermeta.meta_value = nga_calevir_event_categories.id
AND nga_usermeta.meta_key = 'category_id')
GROUP BY nga_calevir_event_categories.id;

第一行的计数似乎增加了一倍。我已经对此进行了几个小时的试验,但我无法弄清楚。有任何想法吗?如果您需要更多信息来帮助我,请告诉我。

【问题讨论】:

    标签: mysql wordpress join count


    【解决方案1】:

    这不起作用,因为连接是组合的:

    SELECT nga_calevir_event_categories.*,
    COUNT(nga_calevir_events.event_id) AS event_total,
    COUNT(nga_usermeta.user_id) AS member_total
    
    
    FROM nga_calevir_event_categories
    LEFT JOIN (nga_calevir_events)
    ON nga_calevir_event_categories.id = nga_calevir_events.event_category
    -- The above is almost the same as an inner join, so long as every 
    -- category has at least one event.
    
    LEFT JOIN (nga_usermeta)
    ON (nga_usermeta.meta_value = nga_calevir_event_categories.id
    AND nga_usermeta.meta_key = 'category_id')
    -- This is where you're going to get weird.  This is going to join 
    -- every row already figured out- basically, a row for every event
    -- with every usermeta that matches!
    
    
    GROUP BY nga_calevir_event_categories.id;
    

    这确实是两个查询 - 没有明智的方法将 usermeta 加入类别(除非我误解了应用程序)。不过,有一种方法可以将其放入一个 SQL 语句中。试试这个:

    SELECT categories.*,
           coalesce(event_hits.hits, 0) + coalesce(meta_hits.hits, 0) as total_hits
    FROM nga_calevir_event_categories as categories       
    
    LEFT JOIN
    (select event_category as catid, count(*) as hits
        FROM (nga_calevir_events)
        group by event_category
    ) as event_hits ON event_hits.catid = categories.id
    
    LEFT JOIN (
       select meta_value as catid, count(*) as hits
       FROM nga_usermeta
       WHERE meta_key = 'category_id'
       group by meta_value
    ) as meta_hits ON meta_hits.catid = categories.id
    

    这使用两个内部选择来获取用于两个表中的每一个的类别 ID 的计数,然后将这些内部选择连接到实际类别,并将它们各自返回的计数相加。我们使用 COALESCE 来确保在其中一张表中没有使用的地方,假定为 0。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-31
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      相关资源
      最近更新 更多