【问题标题】:Query to fetch most recent and highest activity of user查询以获取用户的最新和最高活动
【发布时间】:2013-07-31 08:33:12
【问题描述】:

我的表结构如下:

CREATE TABLE `scores` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `nick` VARCHAR(32) NOT NULL,
    `count` SMALLINT(5) UNSIGNED ZEROFILL NOT NULL DEFAULT '00000',
    `messages` SMALLINT(5) UNSIGNED ZEROFILL NOT NULL DEFAULT '00000',
    `dated` DATE NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `nick_dated` (`nick`, `dated`),
    INDEX `nick` (`nick`),
    INDEX `count` (`count`),
    INDEX `messages` (`messages`)
)
COMMENT='Chat scores'
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

我希望编写一个查询,以便对于nick 的用户输入值,我可以生成用户的:

  • 总数
  • 平均计数
  • 最近一天的计数
  • 最高计数日期

我写的查询是:

SELECT s.`nick` AS `nick`,
    s.`count` AS `recent`,
    t.`total` AS `total`,
    t.`avrg` AS `avrg`,
    MAX(ss.`count`) AS `max`,
    ss.dated
FROM (
    SELECT `nick`,
        SUM(`count`) AS `total`,
        AVG(`count`) AS `avrg`,
        MAX(`dated`) AS `dated` # For most recent activity
    FROM `scores`
    WHERE `nick` = 'hjpotter92'
) AS `t`
INNER JOIN scores s
    ON s.nick = t.nick
        AND s.dated = t.dated
INNER JOIN scores ss
    ON ss.nick = t.nick

我可以选择前三个必需的值。但是我如何才能获得最高活动日期。这是sqlfiddle。正如您在小提琴 DDL 中看到的,line #24

INSERT INTO `scores` 
    (`count`, `nick`, `dated`) 
VALUES 
    (00052, 'hjpotter92', '2013-07-29');

计数最高的日期(MAX(ss.count) 正确获取为 52)是 2013-07-29,但我的选择查询返回我 July, 26 2013

我哪里做错了?

【问题讨论】:

    标签: mysql select join inner-join


    【解决方案1】:

    您的查询是一种奇怪的聚合组合。这是一个有效的版本:

    SELECT s.`nick` AS `nick`,
        srecent.`count` AS `recent`,
        t.`total` AS `total`,
        t.`avrg` AS `avrg`,
        t.maxcount,
        s.dated
    FROM (SELECT `nick`,
                 SUM(`count`) AS `total`,
                 AVG(`count`) AS `avrg`,
                 MAX(`dated`) AS `dated`, # For most recent activity
                 max(count) as maxcount
          FROM `scores`
          WHERE `nick` = 'hjpotter92'
          group by nick
         )  `t` INNER JOIN
        scores s
        ON s.nick = t.nick AND
           s.count = t.maxcount join
        scores srecent
        on srecent.nick = t.nick and
           srecent.dated = t.dated;
    

    原始查询的问题是select 中的max(count)。这将外部select 变成了一个聚合查询——一个返回一行的查询。但是,ss 上的联接返回了多行,因此从该联接返回了任意行。因此结果不一致。

    此版本计算子查询中的各种聚合值。然后它连接回原始表以获取这些日期的其他信息。

    制定查询的另一种方法是使用substring_index(group_concat()) 技巧:

    SELECT `nick`,
           substring_index(group_concat(count order by dated desc), ',', 1) as mostrecent,
           SUM(`count`) AS `total`,
           AVG(`count`) AS `avrg`,
           max(count) as maxcount,
           substring_index(group_concat(dated order by count desc), ',', 1) as dated
    FROM `scores`
    WHERE `nick` = 'hjpotter92'
    group by nick;
    

    【讨论】:

    • 在第一个答案中,我认为您仍然应该在子查询中按 nick 分组,因为您使用的是聚合函数。
    • @鲁本。 . .这不是绝对必要的,但我同意。如果选择多个“昵称”,它会澄清查询并使其更加健壮。
    • 顺便说一下 substring_index(group_concat()) 的巧妙技巧。
    • 因为戈登在这里,我不会尝试回答另一个问题。 +1
    • 我正在使用第一个。虽然SUBSTRING_INDEX 的把戏很不错,但代码会传给后辈,我不希望他们以后质疑我。 :)
    猜你喜欢
    • 2020-08-31
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 2020-06-30
    • 2017-06-15
    • 2011-10-26
    相关资源
    最近更新 更多