我是Oracle分析函数的新手,我正在尝试找到编写查询的最佳方法。
以下是我正在使用的表格的简化版本......
CREATE TABLE my_table
(
pid NUMBER NOT NULL,
my_value NUMBER,
value_date DATE NOT NULL,
CONSTRAINT pk_my_table PRIMARY KEY (pid, value_date)
);
请注意,“value_date”是主键的一部分。
对于每个“pid”,我希望查询显示5列:
pid
2.最近7天数据的“my_value”的最大值
3.最多7天的相应日期(value_date)
4.最近30天数据的“my_value”的最大值
5.最多30天的相应日期(value_date)
没有加入可以做到这一点吗?实现这一目标的最佳方法是什么?
提前感谢您的帮助,
卡尔
答案 0 :(得分:3)
我无法得到我在这里寻找的答案所以我在Oracle论坛上发布了这个问题。我得到的答案正是我所寻找的。以下查询仅通过表中的一次传递获得答案,并且没有任何连接...
SELECT pid,
MAX(CASE
WHEN value_date > TRUNC (SYSDATE) - 6 THEN my_value
ELSE 0
END)
max_7_days,
MAX(value_date)
KEEP (DENSE_RANK FIRST ORDER BY
(CASE
WHEN value_date >
TRUNC (SYSDATE) - 6
THEN
my_value
ELSE
0
END) DESC)
day_7_days,
MAX(CASE
WHEN value_date > TRUNC (SYSDATE) - 29 THEN my_value
ELSE 0
END)
max_30_days,
MAX(value_date)
KEEP (DENSE_RANK FIRST ORDER BY
CASE
WHEN value_date >
TRUNC (SYSDATE) - 29
THEN
my_value
ELSE
0
END DESC)
day_30_days
FROM my_table
GROUP BY pid;
如果有人想测试它,这里有一些示例数据。
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 300, '18-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 200, '17-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 4500, '16-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 800, '15-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 12000, '14-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 21000, '13-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 5600, '12-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 18400, '11-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 7200, '10-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 24000, '09-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 8800, '08-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 6000, '07-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 44200, '06-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 2800, '05-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 58500, '04-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 8000, '03-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 30600, '02-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 7200, '01-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 62700, '31-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 48000, '30-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 16800, '29-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 83600, '28-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 18400, '27-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 16800, '26-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 40000, '25-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 23400, '24-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 99900, '23-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 67200, '22-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 5800, '21-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 57000, '20-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 96100, '19-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 64000, '18-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 52800, '17-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 71400, '16-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 14000, '15-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 7200, '14-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 111000, '13-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 64600, '12-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 113100, '11-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (1, 84000, '10-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 6000, '18-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 7800, '17-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 13500, '16-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 25600, '15-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 276000, '14-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 210000, '13-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 162400, '12-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 36800, '11-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 86400, '10-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 480000, '09-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 8800, '08-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 102000, '07-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,1237600, '06-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 61600, '05-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,1287000, '04-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 144000, '03-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 275400, '02-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 93600, '01-FEB-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,1630200, '31-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,1248000, '30-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 235200, '29-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,3176800, '28-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 73600, '27-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 403200, '26-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 200000, '25-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 280800, '24-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 599400, '23-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,1612800, '22-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 110200, '21-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,1653000, '20-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,2498600, '19-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,2368000, '18-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 211200, '17-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,2570400, '16-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 224000, '15-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 223200, '14-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2, 999000, '13-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,2325600, '12-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,1017900, '11-JAN-10');
INSERT INTO my_table (pid, my_value, value_date) VALUES (2,2352000, '10-JAN-10');
感谢大家回答这个问题所做的努力!
卡尔
答案 1 :(得分:2)
我认为这对你来说是正确的解决方案。我刚刚在浏览器中键入它并且没有测试过。我认为这应该对你有所帮助......至少试图给你一个想法...
SELECT table_7_day_info.pid
,table_7_day_info.max_val_7_day
,table_7_day_info.max_day_7_day
,table_30_day_info.max_val_30_day
,table_30_day_info.max_day_30_day
FROM
(
SELECT t1.pid, t1.my_value max_val_7_day, t1.value_date max_day_7_day
FROM my_table t1
WHERE (t1.pid,t.my_value) in (
SELECT t.pid, max(t.my_value)
FROM my_table t
WHERE t.value_date >= sysdate - 7
GROUP BY t.pid
)
) table_7_day_info,
(
SELECT t2.pid, t2.my_value max_val_30_day, t2.value_date max_day_30_day
FROM my_table t2
WHERE (t2.pid,t2.my_value) in (
SELECT t3.pid, max(t3.my_value)
FROM my_table t3
WHERE t3.value_date >= sysdate - 30
GROUP BY t3.pid
)
) table_30_day_info,
WHERE table_7_day_info.pid = table_7_day_info.pid
答案 2 :(得分:1)
您可以在同一时间间隔内一次获取信息。即最近7天的信息,以及最近30天的信息。但要将这些数据放在一起,您需要加入:
select nvl(week.pid,mon.pid)
, week.week_val
, week.week_date
, mon.month_val
, mon.month_date
from (
select pid
, max(my_value) month_val
, max(value_date) keep (dense_rank last order by my_value) month_date
from my_table
where value_date >= sysdate - 30
group by pid
) mon
left outer join
(
select pid
, max(my_value) week_val
, max(value_date) keep (dense_rank last order by my_value) week_date
from my_table
where value_date >= sysdate - 7
group by pid
) week
on (mon.pid = week.pid)
;
这里我使用了左外连接,因为你可能在一周内没有数据但在一个月内有一些数据。
答案 3 :(得分:0)
SELECT A.PID,A.VALUE_DATE_7DYMAX, A.MY_VALUE, B.VALUE_DATE_30DYMAX, B.MY_VALUE FROM (SELECT * FROM (select pid,my_value, VALUE_DATE AS VALUE_DATE_7DYMAX, row_number() over(partition by pid order by MY_VALUE desc) rn FROM MY_TABLE
where value_date between TO_DATE('11-JAN-10','DD-MON-YY') AND TO_DATE('21-JAN-10','DD-MON-YY'))where RN =1) A ,
(SELECT * FROM (select pid,my_value, VALUE_DATE AS VALUE_DATE_30DYMAX, row_number() over(partition by pid order by MY_VALUE desc) rn FROM MY_TABLE
where value_date between TO_DATE('11-JAN-10','DD-MON-YY') AND TO_DATE('21-FEB-10','DD-MON-YY'))where RN =1) B
WHERE A. PID =B.PID
答案 4 :(得分:0)
此解决方案仅涉及2个表格,并且不使用硬编码日期。
我使用row_number()的2个子查询基本上基于value_date进行排序,以分别获得7天范围和30天范围内的最新日期。使用该数据集已经基于最大my_value对记录进行了排名,选择了具有rank = 1并且具有最大值&的最高记录。相应的和日期。
PID | MAXVAL_7DAY | MAXVALDATE_7DAY | MAXVAL_30DAY | MAXVALDATE_30DAY
1 | 21000 | 8/13/2015 | 99900 | 7/23/2015
2 | 276000 | 8/14/2015 | 3176800 | 7/28/2015
以下是输出:
std::string
答案 5 :(得分:-1)
select t.*,
max(my_value) over(partition by pid order by value_date range between 0 preceding and 7 following) recent7value,
max(value_date) over(partition by pid order by value_date range between 0 preceding and 7 following) recent7date,
max(my_value) over(partition by pid order by value_date range between 0 preceding and 30 following) recent30value,
max(value_date) over(partition by pid order by value_date range between 0 preceding and 30 following) recent30date
from my_table t
order by pid,
value_date;