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

MySQL中的表JOIN和聚合问题

  •  1
  • beny  · 技术社区  · 17 年前

    我有三张桌子。此查询将写下正确的答案(btv.id_user的x行,带有适当的btv.cas和race.id_zavod

    SELECT `btv.id_user`, `btv.id_zavod`,`btv.cas`
    FROM `btv`
    JOIN `btu` ON `btv.id_user` = `btu.id_user`
    JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
    WHERE `race.type` = '8' AND `btv.id_user` = '607'
    

    结果:

    | 607 |  512 | 03:15:58 |  
    | 607 |  730 | 03:01:18 |  
    | 607 |  164 | 03:07:26 |  
    | 607 |  767 | 02:58:31 |  
    | 607 | 1147 | 03:06:47 |  
    | 607 | 1149 | 03:09:41 |  
    | 607 | 1178 | 03:24:20 | 
    

    但是,当我尝试通过id_user将其聚合到一行时,它返回正确的min btv.cas,但错误的join错误的race.id_zavod

    SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
    FROM `btv`
    JOIN `btu` ON `btv.id_user` = `btu.id_user`
    JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
    WHERE `race.type` = '8' AND `btv.id_user` = '607'
    GROUP BY `btv.id_user`
    

    结果:

    | 607 | 512 | 02:58:31 |
    
    5 回复  |  直到 17 年前
        1
  •  0
  •   Bill Karwin    17 年前

    您编写的查询:

    SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
    FROM `btv`
    JOIN `btu` ON `btv.id_user` = `btu.id_user`
    JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
    WHERE `race.type` = '8' AND `btv.id_user` = '607'
    GROUP BY `btv.id_user`

    不会跑。你需要一个按id_zavod或其他方式分组。你能告诉我们你真正在运行什么查询吗?你期望的结果是什么?

        2
  •  1
  •   user12861    17 年前

    使用GROUP BY时,选择列表中的列必须满足以下条件之一:

    • 列在GROUP BY中命名(例如。 btv.id_user 在您的示例中)
    • 列位于聚合函数内部(例如。 MIN( btv.cas ) )
    • 列是一个 函数依赖 您在GROUP BY中指定的列。

    这是您的查询中的错误: btv.id_zavod 每个值都有许多值 btv.id_user 这不满足功能依赖性。中只能有一个值 id_zavod 对于每个值 id_user 因为它是一种功能依赖。

    在某些数据库品牌中,此查询实际上会给您一个错误。MySQL更灵活,只信任您在选择列表中命名列,这些列是您在GROUP BY中命名的列的函数依赖关系。

    这是一个查询,返回您想要的MIN值 btv.cas id_user ,对应值为 btv.id_zavod :

    SELECT b1.id_user, b1.id_zavod, b1.cas
    FROM btv AS b1
     JOIN btu ON (b1.id_user = btu.id_user)
     JOIN race ON (b1.id_zavod = race.id_zavod)
     LEFT OUTER JOIN btv AS b2 ON (b1.id_user = bt2.id_user AND 
       (b1.cas > b2.cas OR (b1.cas = b2.cas AND b1.primarykey > b2.primarykey))
    WHERE race.type = '8' AND b1.id_user = '607'
     AND b2.id_user IS NULL;
    

    换句话说,你需要像以前一样进行加入,但然后加入 btv 再次,查看是否有另一行具有相同的内容 id_user 值和较小的值 cas .使用OUTER JOIN,因为您正在寻找没有匹配的情况。你可以通过以下方式进行测试 b2.id_user IS NULL ,因为当没有匹配项时,OUTER JOIN会使所有列为NULL。

    请注意,可能存在联系,因此我们使用主键作为联系破坏者添加了额外的术语。

    您不需要在此查询中使用GROUP BY。这是隐式处理的,因为只有一行满足OUTER JOIN条件。

        3
  •  0
  •   Jason Michael    17 年前

    尝试:

    SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
    FROM `btv`
    Inner JOIN `btu` ON `btv.id_user` = `btu.id_user`
    Inner JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
    WHERE `btv.id_user` = '607'
    GROUP BY `btv.id_user` having `race.type` = '8'
    
        4
  •  0
  •   Shinhan    17 年前

    我不确定你想实现什么,但你是否在寻找 GROUP_CONCAT function? ?

        5
  •  0
  •   Pianosaurus    17 年前

    您是否只是试图获取最低的btv.cas值及其其他相应列?如果是这样,您可以通过btv.cas订购,并限制为1次点击:

    SELECT `btv.id_user`, `btv.id_zavod`,`btv.cas`
    FROM `btv`
    JOIN `btu` ON `btv.id_user` = `btu.id_user`
    JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
    WHERE `race.type` = '8' AND `btv.id_user` = '607'
    ORDER BY `btv.cas` LIMIT 1
    推荐文章