【问题标题】:MySQL - How to GROUP BY more columns and SUM() each group?MySQL - 如何按更多列和 SUM() 每组分组?
【发布时间】:2013-08-14 17:53:40
【问题描述】:

目前我的查询如下所示:

SELECT alias.name killer,
       SUM(kill_stats.amount) amount
FROM kill_stats
        JOIN pickup ON pickup.logfile = 'CTFCL-20130813-1456-shutdown2'
        JOIN account ON account.steam_id = '0:1:705272'
        JOIN player victim ON victim.pickup_id = pickup.id AND victim.account_id = account.id
        JOIN player killer ON killer.pickup_id = pickup.id AND kill_stats.killer_id = killer.id
        JOIN alias ON killer.alias_id = alias.id
WHERE kill_stats.victim_id = victim.id AND NOT killer.team_id = victim.team_id
GROUP BY kill_stats.killer_id
ORDER BY amount DESC

kill_stats表格布局:

CREATE TABLE `kill_stats` (
  `killer_id` int(11) UNSIGNED NOT NULL,
  `victim_id` int(11) UNSIGNED NOT NULL,
  `weapon_id` int(11) UNSIGNED NOT NULL,
  `conced` bit(1) NOT NULL,
  `fc` bit(1) NOT NULL,
  `amount` int(11) UNSIGNED NOT NULL,
  PRIMARY KEY(`killer_id`, `victim_id`, `weapon_id`, `conced`, `fc`),
  CONSTRAINT `Ref_Killer` FOREIGN KEY (`killer_id`)
    REFERENCES `player`(`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `Ref_Victim` FOREIGN KEY (`victim_id`)
    REFERENCES `player`(`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `Ref_Weapon` FOREIGN KEY (`weapon_id`)
    REFERENCES `weapon`(`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE
)
ENGINE=INNODB
CHARACTER SET utf8 
COLLATE utf8_unicode_ci ;

这里是用虚拟数据替换外键的更易读的视图:

+-----------+-----------+-----------+--------+----+--------+
| killer_id | victim_id | weapon_id | conced | fc | amount |
+-----------+-----------+-----------+--------+----+--------+
| Josephine |   Frank   |    RPG    |   NO   | NO |   14   |
+-----------+-----------+-----------+--------+----+--------+
| Josephine |   Frank   |  Shotgun  |   YES  | NO |   5    |
+-----------+-----------+-----------+--------+----+--------+
| Josephine |   Frank   |  Shotgun  |   NO   | NO |   3    |
+-----------+-----------+-----------+--------+----+--------+
| Miguel    |   Frank   |   Knife   |   NO   | NO |   1    |
+-----------+-----------+-----------+--------+----+--------+

使用此示例表,上面的查询将返回如下表:

+-----------+--------+
|  killer   | amount |
+-----------+--------+
| Josephine |   22   |
+-----------+--------+
|  Miguel   |   1    |
+-----------+--------+

我想要的输出是:

+-----------+-------------+--------------+-----------------+
|  killer   | total_kills | conced_kills | victim_had_flag |
+-----------+-------------+--------------+-----------------+
| Josephine |      22     |      5       |        0        |
+-----------+-------------+--------------+-----------------+
|  Miguel   |      1      |      0       |        0        |
+-----------+-------------+--------------+-----------------+

显示某个玩家被其他玩家杀死的频率、他们杀死他的总次数、被击杀的数量以及玩家在被他们杀死时携带旗帜的频率。

我不太确定如何实现,我尝试过GROUP BY kill_stats.killer_id, kill_stats.conced,但结果是:

+-----------+--------+
|   killer  | amount |
+-----------+--------+
| Josephine |   14   |  -> the ones with kill_stats.conced = NO
+-----------+--------+
| Josephine |   5    |  -> the ones with kill_stats.conced = YES
+-----------+--------+
| Miguel    |   1    |  -> the ones with kill_stats.conced = NO (only row for that `killer_id`)
+-----------+--------+

我为killer_id 获得了多行,我希望每个killer_id一个 行来保存所有数据。

Ike Walker 的解决方案几乎就是我一直在寻找的解决方案,使其按我想要的方式工作的最终查询是:

SELECT alias.name killer,
       SUM(kill_stats.amount) as total_kills ,
       SUM(CASE WHEN kill_stats.conced then kill_stats.amount ELSE 0 END) as conced_kills ,
       SUM(CASE WHEN kill_stats.fc then kill_stats.amount ELSE 0 END) as victim_had_flag 
    FROM kill_stats
        JOIN pickup ON pickup.logfile = 'CTFCL-20130813-1456-shutdown2'
        JOIN account ON account.steam_id = '0:1:705272'
        JOIN player victim ON victim.pickup_id = pickup.id AND victim.account_id = account.id
        JOIN player killer ON killer.pickup_id = pickup.id AND kill_stats.killer_id = killer.id
        JOIN alias ON killer.alias_id = alias.id
WHERE kill_stats.victim_id = victim.id AND NOT killer.team_id = victim.team_id
GROUP BY kill_stats.killer_id
ORDER BY amount DESC

最终让我走上正轨的他的解决方案的不同之处在于,我总是需要 SUM() kill_stats.amount 进入新列 conced_kills 为每一行包含 @987654334 @ 列设置为 1。

【问题讨论】:

    标签: mysql join group-by sum multiple-columns


    【解决方案1】:

    执行此操作的标准方法是将SUM()CASE 组合起来作为次要计数。

    这是您以这种方式重写的示例查询,以提供您正在寻找的输出:

    SELECT alias.name killer,
           SUM(kill_stats.amount) as total_kills ,
           SUM(CASE WHEN kill_stats.conced then 1 ELSE 0 END) as conced_kills ,
           SUM(CASE WHEN kill_stats.fc then 1 ELSE 0 END) as victim_had_flag 
    FROM kill_stats
            JOIN pickup ON pickup.logfile = 'CTFCL-20130813-1456-shutdown2'
            JOIN account ON account.steam_id = '0:1:705272'
            JOIN player victim ON victim.pickup_id = pickup.id AND victim.account_id = account.id
            JOIN player killer ON killer.pickup_id = pickup.id AND kill_stats.killer_id = killer.id
            JOIN alias ON killer.alias_id = alias.id
    WHERE kill_stats.victim_id = victim.id AND NOT killer.team_id = victim.team_id
    GROUP BY kill_stats.killer_id
    ORDER BY amount DESC
    

    【讨论】:

      【解决方案2】:

      尝试将查询的 SELECT 列表更改为:

      SELECT alias.name killer,
         SUM(kill_stats.amount) amount,
         SUM(kill_stats.conced) conced_kills,
         SUM(kill_stats.fc) victim_had_flag
      

      ...然后拿起FROM kill_stats 并完全按照您发布的内容完成它。我假设conced 如果为真则为 1,如果为假则为 0;与fc 相同。我还假设fc 表示“受害者有标志”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多