代码之家  ›  专栏  ›  技术社区  ›  okoman

具有两个联接的聚合(MySQL)

  •  2
  • okoman  · 技术社区  · 17 年前

    我有一张桌子叫 画廊 画廊 在那里,每一行都是某个画廊的赞成票或反对票。 以下是(简化)结构:

    gallery ( gallery_id )
    picture ( picture_id, picture_gallery_ref )
    vote ( vote_id, vote_value, vote_gallery_ref )
    

    现在,我想通过一个查询来获得以下信息:所有拥有自己数据字段的画廊、连接到画廊的图片数量以及投票的汇总值。

    这是我的查询,但由于多重连接,聚合值不是正确的。(至少当有多行图片或投票时。)

    SELECT 
      *, SUM( vote_value ) as score, COUNT( picture_id ) AS pictures
    FROM 
      gallery
    LEFT JOIN 
      vote
      ON gallery_id = vote_gallery_ref
    LEFT JOIN 
      picture
      ON gallery_id = picture_gallery_ref
    GROUP BY gallery_id
    

    COUNT( DISTINCT picture_id ) 给出了我尝试的正确图片数量:

    ( SUM( vote_value ) / GREATEST( COUNT( DISTINCT picture_id ), 1 ) ) AS score
    

    它在这个例子中是有效的,但如果一个查询中有更多的连接呢?

    4 回复  |  直到 17 年前
        1
  •  5
  •   Bill Karwin    17 年前

    Okham的William的这句话适用于这里:

    Enita不需要乘法运算

    (拉丁语为“实体不得超过必要性”)。

    你应该重新考虑一下 为什么需要在单个查询中完成此操作? 然后运行单独的查询。

        2
  •  3
  •   Kev    17 年前

    或者只使用子查询。..

    我不知道这是否是有效的MySQL语法,但你可以做类似的事情:

    SELECT
      gallery.*, a.score, b.pictures
    LEFT JOIN
    (
      select vote_gallery_ref, sum(vote_value) as score
      from vote
      group by vote_gallery_ref
    ) a ON gallery_id = vote_gallery_ref
    LEFT JOIN 
    (
      select picture_gallery_ref, count(picture_id) as pictures
      from picture
      group by picture_gallery_ref
    ) b ON gallery_id = picture_gallery_ref
    
        3
  •  1
  •   Paul Morgan    17 年前

    您多久添加/更改一次投票记录?

    您多久添加/删除一次图片记录?

    您多久对这些总计运行一次此查询?

    最好在库表上创建总计字段( total_pictures, total_votes, total_vote_values ).

    在图片表上添加或删除记录时,也会更新库表上的总数。这可以使用图片表上的触发器自动更新库表来完成。也可以使用结合两个SQL语句的事务来更新图片表和图库表。在图片表上添加记录时,递增 total_pictures 画廊桌子上的田地。当您删除图片表上的记录时 总计_图片 现场。

    类似地,当添加或删除投票记录或 vote_value 您更新的更改 total_votes total_vote_values 领域。添加记录会增加 总计_记录 字段并添加 vote_values 总计_值 .删除记录会减少 总计_记录 字段和减法 vote_values 总计_值 .更新 vote_values 投票记录也应更新 总计_值 用差值(减去旧值,加上新值)。

    现在,您的查询变得微不足道——它只是库表中的一个简单查询。但这是以对图片和投票表进行更复杂的更新为代价的。

        4
  •  0
  •   matt b    17 年前

    正如比尔·卡温所说,在一个查询中完成这一切是相当丑陋的。

    name state :

    select g.gallery_id, g.name, g.state, i.num_pictures, j.sum_vote_values
    from gallery g
    inner join (
      select g.gallery_id, count(p.picture_id) as 'num_pictures'
      from gallery g
      left join picture p on g.gallery_id = p.picture_gallery_ref
      group by g.gallery_id) as i on g.gallery_id = i.gallery_id
    left join (
      select g.gallery_id, sum(v.vote_value) as 'sum_vote_values'
      from gallery g
      left join vote v on g.gallery_id = v.vote_gallery_ref
      group by g.gallery_id
    ) as j on g.gallery_id = j.gallery_id
    

    这将产生一个结果集,如下所示:

    gallery_id, name, state, num_pictures, sum_vote_values
    1, 'Gallery A', 'NJ', 4, 19
    2, 'Gallery B', 'NY', 3, 32
    3, 'Empty gallery', 'CT', 0,