根据最大聚合函数对同一列进行计数
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
我正在尝试获取最新游戏的日期以及玩家在之前 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