根据最大聚合函数对同一列进行计数

depending on the max aggregate function to count the same column

我正在尝试获取最新游戏的日期以及玩家在之前 window 的 1 小时内进行的游戏数量。

这是我要执行的代码

SELECT MAX(saved_date), COUNT(saved_date) FROM Game
WHERE username = 'user_name'
HAVING saved_date >= MAX(saved_date) - interval '1' hour;

但它给了我错误 not a GROUP BY expression。当我添加行 GROUP BY saved_date 时,错误没有出现,但它没有回答我的第一个问题。我知道我可以在两个语句中完成,但我更喜欢在一个语句中完成。

你有什么建议或解决办法吗?由于这是我第一次post来这里,请多多包涵,谢谢!

附加信息:

Game table 是这样创建的:

CREATE TABLE GAME (
    game_id NUMBER GENERATED ALWAYS AS IDENTITY,
    ...
    saved_date DATE,
    ...
);

输出 GROUP BY saved_date :

MAX(saved_date) | COUNT(saved_date)
----------------|------------------
 29/03/21       | 1
 29/03/21       | 1 
 29/03/21       | 1

期望的输出:

MAX(saved_date) | COUNT(saved_date)
----------------|------------------
 29/03/21       | 3

您需要一个子查询。我会使用 window 函数来解决这个问题:

SELECT MAX(saved_date), COUNT(*)
FROM (SELECT G.*,
             MAX(G.saved_date) OVER (PARTITION BY G.username) as max_saved_date
      FROM Game G
      WHERE G.username = 'user_name'
     ) G
WHERE saved_date >= max_saved_date - interval '1' hour;

您可以使用分析函数(而不是聚合函数):

SELECT saved_date,
       COUNT(*) OVER (
         ORDER BY saved_date DESC
         RANGE BETWEEN INTERVAL '0' HOUR PRECEDING
               AND     INTERVAL '1' HOUR FOLLOWING
       ) AS num_games
FROM   game
WHERE  username = 'user_name'
ORDER BY saved_date DESC
FETCH FIRST ROW ONLY;

或者,如果您使用的是 Oracle 11g:

SELECT saved_date,
       num_games
FROM   (
  SELECT ROW_NUMBER() OVER ( ORDER BY saved_date DESC ) AS rn,
         saved_date,
         COUNT(*) OVER (
           ORDER BY saved_date DESC
           RANGE BETWEEN INTERVAL '0' HOUR PRECEDING
                 AND     INTERVAL '1' HOUR FOLLOWING
         ) AS num_games
  FROM   game
  WHERE  username = 'user_name'
)
WHERE  rn = 1;

其中,对于示例数据:

CREATE TABLE GAME (
    game_id    NUMBER GENERATED ALWAYS AS IDENTITY,
    username   VARCHAR2(100),
    saved_date DATE
);

INSERT INTO game ( username, saved_date )
SELECT 'user_name', DATE '1970-01-01' + ( LEVEL - 1 ) * INTERVAL '10' MINUTE
FROM   DUAL
CONNECT BY LEVEL <= 20;

输出:

SAVED_DATE          | NUM_GAMES
:------------------ | --------:
1970-01-01 03:10:00 |         7

db<>fiddle here