如何从 oracle sql 获取下个月的条目?

发布于 2024-08-07 22:32:51 字数 182 浏览 3 评论 0原文

假设我有一个包含“user_id、日期、分数”的表,每个用户每个月都有一个分数,但并不总是在同一天。

我想要一个包含“user_id,date,score_delta”的查询,其中score_delta是“日期”和下个月之间分数会发生多少变化?我是否必须做一些蹩脚的事情,比如 to_date(to_char(date, ... )?

Let's say I have a table that has "user_id, date, score", and every user has exactly one score every month, but not always on the same day.

I want a query that has "user_id, date, score_delta" where score_delta is how much the score will change between "date" and the next month? Am I going to have to do something lame like to_date(to_char(date, ... ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盛夏尉蓝 2024-08-14 22:32:51

这是一种方法(跛行商计算留给读者作为练习):

CREATE TABLE scores (user_id VARCHAR2(32), test_date DATE, score NUMBER);

INSERT INTO scores VALUES('U1',SYSDATE-61, 85);
INSERT INTO scores VALUES('U1',SYSDATE-31, 89);
INSERT INTO scores VALUES('U1',SYSDATE, 92);
INSERT INTO scores VALUES('U2',SYSDATE-61, 65);
INSERT INTO scores VALUES('U2',SYSDATE-31, 89);
INSERT INTO scores VALUES('U2',SYSDATE, 84);

COMMIT;

SELECT s1.user_id, s1.test_date, s2.score-s1.score delta
  FROM scores s1 
       JOIN (SELECT user_id, trunc(test_date,'MM') test_date, score FROM scores) s2
         ON (s1.user_id = s2.user_id AND
             trunc(add_months(s1.test_date,1),'MM') = s2.test_date);

USER_ID                          TEST_DATE        DELTA
-------------------------------- ---------   ----------
U1                               9/15/2009            3
U1                               8/16/2009            4
U2                               9/18/2009           -5
U2                               8/19/2009           24

编辑:这是一个缓慢的下午,所以我决定研究 10g 提供的分析函数内容(进一步将自己拖入当前的世纪;-),并使用 LAG 函数重写了上面的内容:

SELECT user_id, test_date, score
     , LAG(score, 1, NULL) OVER (PARTITION BY user_id ORDER BY test_date DESC) - score delta
     , LAG(score, 1, NULL) OVER (PARTITION BY user_id ORDER BY test_date DESC) AS next_score
  FROM scores
 ORDER BY 1, 2 DESC;

产生:

USER_ID                          TEST_DATE        SCORE      DELTA NEXT_SCORE
-------------------------------- ----------- ---------- ---------- ----------
U1                               10/19/2009          92            
U1                               9/18/2009           89          3         92
U1                               8/19/2009           85          4         89
U2                               10/19/2009          84            
U2                               9/18/2009           89         -5         84
U2                               8/19/2009           65         24         89

看,马!不准自行加入!现在这很光滑;-)(顺便说一句,解释计划表明自连接效率不高)。

作为跳板,我从这个 询问tom.com问题

Here's one way (lameness quotient calculation left as an exercise to the reader):

CREATE TABLE scores (user_id VARCHAR2(32), test_date DATE, score NUMBER);

INSERT INTO scores VALUES('U1',SYSDATE-61, 85);
INSERT INTO scores VALUES('U1',SYSDATE-31, 89);
INSERT INTO scores VALUES('U1',SYSDATE, 92);
INSERT INTO scores VALUES('U2',SYSDATE-61, 65);
INSERT INTO scores VALUES('U2',SYSDATE-31, 89);
INSERT INTO scores VALUES('U2',SYSDATE, 84);

COMMIT;

SELECT s1.user_id, s1.test_date, s2.score-s1.score delta
  FROM scores s1 
       JOIN (SELECT user_id, trunc(test_date,'MM') test_date, score FROM scores) s2
         ON (s1.user_id = s2.user_id AND
             trunc(add_months(s1.test_date,1),'MM') = s2.test_date);

USER_ID                          TEST_DATE        DELTA
-------------------------------- ---------   ----------
U1                               9/15/2009            3
U1                               8/16/2009            4
U2                               9/18/2009           -5
U2                               8/19/2009           24

EDIT: It's a slow afternoon, so I decided to look into this analytic function stuff that 10g offers (further dragging myself into the current century ;-), and rewrote the above using the LAG function:

SELECT user_id, test_date, score
     , LAG(score, 1, NULL) OVER (PARTITION BY user_id ORDER BY test_date DESC) - score delta
     , LAG(score, 1, NULL) OVER (PARTITION BY user_id ORDER BY test_date DESC) AS next_score
  FROM scores
 ORDER BY 1, 2 DESC;

Which produces:

USER_ID                          TEST_DATE        SCORE      DELTA NEXT_SCORE
-------------------------------- ----------- ---------- ---------- ----------
U1                               10/19/2009          92            
U1                               9/18/2009           89          3         92
U1                               8/19/2009           85          4         89
U2                               10/19/2009          84            
U2                               9/18/2009           89         -5         84
U2                               8/19/2009           65         24         89

Look, Ma! No self-join! Now THAT's slick ;-) (As an aside, the explain plans indicate the self-join is not as efficient).

As a springboard, I started with this asktom.com question.

不忘初心 2024-08-14 22:32:51

像这样的东西应该返回下个月输入的 user_id、日期和分数。

select user_id, date, score  from table where
date between ((select sysdate from dual)
and (select add_months(sysdate, 1) FROM dual));

Something like this should return the user_id, date and score entered next month.

select user_id, date, score  from table where
date between ((select sysdate from dual)
and (select add_months(sysdate, 1) FROM dual));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文