【问题标题】:MySQL Group By with Sum removing too much informationMySQL Group By with Sum 删除了太多信息
【发布时间】:2011-10-04 11:45:23
【问题描述】:

谁能帮助我了解 MySQL 的 Group By 的工作原理以及我做错了什么?我正在使用一个包含两个表、拍卖和批次的数据库。批次表有一个“auctionid”列,它将每个批次链接到相关的拍卖,拍卖和批次之间具有一对多的关系。

我从批次和拍卖中选择大量信息,包括使用几个 sum 和 count(distinct) 函数在每次拍卖的基础上汇总批次表中的一些记录。

我的查询是这样的:

SELECT
  auction.`countryId`,
  auction.`date`,
  auction.`name`,
  auction.`awardComments`,
  lots.`lotName`,
  lots.`region`,
  lots.`popCovered`,

  SUM(lots.'size'),
  SUM(lots.`paired`),
  SUM(lots.`unpaired`),
  COUNT(DISTINCT 'lots.winner')

FROM auction join lots USING ('awardid') 

GROUP BY lots.'awardid'

'awardid' 是拍卖表的主键和批次表的外键。 'lotid' 是批次表的主键,但未使用。

当我运行此查询时,我会为每个拍卖获得一行,我正在寻找的是每个批次的一行,该拍卖中每个批次的拍卖信息相同,并且 sum 和 count 函数计算总数拍品表中每次拍卖的大小和获胜者数量。如果我去掉查询的“分组依据”和“求和”部分,那么我得到的行数是正确的,每批一个。有没有办法通过 sum 和 count 函数获得我需要的所有行?基本上我只希望 group 子句适用于 SUM 和 COUNT 函数,如果这有意义的话 - 我希望计算每次拍卖的获胜者数量,但显示在该拍卖中每批的结果中。

【问题讨论】:

  • 这个表的候选键是什么?
  • 看起来您在表格列表中漏掉了一个逗号:from auction, lots
  • @eugeney,他实际上错过了join 关键字。
  • @JStead,我不知道候选键是什么 - 'awardid' 是拍卖表的主键,还将每个批次记录链接到其父拍卖。
  • @Johan,是的,我在编辑查询时不小心删除了“加入”关键字,然后重新添加,谢谢。

标签: mysql count group-by sum


【解决方案1】:
SELECT
  a.countryId,
  a.`date`,
  a.name,
  a.awardComments,
  l.lotName,
  l.region,
  l.popCovered,

  sums.total_size,
  sums.total_paired,
  sums.total_unpaired,
  sums.winners

FROM auction a
INNER JOIN lots l on (a.awardid = l.awardid) 
INNER JOIN (
  SELECT 
    a2.id as auction_id
    SUM(l2.size) as total_size,
    SUM(l2.paired) as total_paired,
    SUM(l2.unpaired) as total_unpaired,
    COUNT(DISTINCT l2.winner) as winners
  FROM AUCTION a2 INNER JOIN lots l2 ON (a2.awardid = l2.awardid)
  GROUP BY a2.id
  ) sums ON (sums.auction_id = a.id) 

对于来自同一拍卖的拍品,每次拍卖都会重复相同的总数。

【讨论】:

  • @IlmariKaronen,我知道,OP 特别要求每手 1 行。他已经有每次拍卖的查询。
  • 这给了我正确的行数,但是 SUM 和 COUNT 函数并没有跨批次求和,它们只是给了我那个批次的答案——每个批次都有一个赢家,但我想看看每次拍卖有多少不同的获胜者。我希望每个拍品行都包含有关整个拍卖以及特定拍品的信息。
  • 您需要做的就是将您所说的查询的 GROUP BY 子句修改为 GROUP BY a.id, l.id WITH ROLLUP 之类的东西——检查一下:dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html
  • @Dereleased,这是不正确的。 GROUP BY a.id, l.idgroup by l.id 相同,并且 with rollup 将为所有拍卖提供 一个 的总计;即如果涉及超过 1 次拍卖,将给出错误的结果。不过,WITH ROLLUP 总的来说不是一个坏主意。
  • @约翰。效果很好,非常感谢您的帮助。
【解决方案2】:

我想这样的事情可能会起作用(警告:未经测试!):

SELECT 
  auction.`countryId`,
  auction.`date`,
  auction.`name`,
  auction.`awardComments`,
  lots.`lotName`,
  lots.`region`,
  lots.`popCovered`,
  sums.`size`,
  sums.`paired`,
  sums.`unpaired`,
  sums.`winners`
FROM auction
JOIN lots USING (`awardid`)
JOIN (
  SELECT
    `awardid`,
    SUM(`size`) AS `size`,
    SUM(`paired`) AS `paired`,
    SUM(`unpaired`) AS `unpaired`,
    COUNT(DISTINCT lots.`winner`) AS `winners`
  FROM lots GROUP BY `awardid`
) AS sums USING (`awardid`)

也就是说,您对 lots 表进行子选择以计算每次拍卖的总和,然后将其结果视为可以加入结果的单独表。

【讨论】:

  • 你只是复制粘贴我的答案吗:-?尽管using 子句模棱两可,但我认为它不会起作用。子选择会添加所有拍品,无论它们属于哪个拍卖。
  • @Johan:伟大的思想都一样。 :) 无论如何,子选择应该起作用:记住lots.awardid 是拍卖表的外键,所以具有相同awardid 的批次属于同一个拍卖。不过,您可能对USING 语法是正确的;我认为它应该可以正常工作,但我还没有测试过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-15
  • 1970-01-01
相关资源
最近更新 更多