【问题标题】:depending on the max aggregate function to count the same column取决于最大聚合函数来计算同一列
【发布时间】:2021-03-29 21:03:34
【问题描述】:

我正在尝试获取最新游戏的日期以及玩家在此之前 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 行时,错误没有出现,但它没有回答我的第一个问题。我知道我可以在两个语句中完成,但我更喜欢在一个语句中完成。

您有什么建议或解决方案吗?由于这是我在这里的第一篇文章,请放纵,谢谢!

附加信息:

Game 表是这样创建的:

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

【问题讨论】:

  • 您已标记 Oracle 11g;但是,直到 Oracle 12 才支持 GENERATED ALWAYS AS IDENTITY 语法。您使用的是哪个版本?
  • 你真的确定GROUP BY saved_date ..的结果吗?

标签: sql oracle oracle11g


【解决方案1】:

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

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;

输出:

保存日期 | NUM_GAMES :----------------- | --------: 1970-01-01 03:10:00 | 7

db小提琴here

【讨论】:

    【解决方案2】:

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

    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;
    

    【讨论】:

      猜你喜欢
      • 2021-08-16
      • 2018-01-06
      • 1970-01-01
      • 1970-01-01
      • 2018-01-23
      • 2018-01-14
      • 2021-06-16
      • 1970-01-01
      • 2021-04-13
      相关资源
      最近更新 更多