使用 ORACLE 从不同行查询数据 SQL
Querying data from different rows using ORACLE SQL
我有这个table:
+------+-------+---------+----------------------------+
| id | date | value | value2 | value3 |
+------+-------+---------+----------------------------+
| 1 | 5/28 | 100 | NULL | NULL |
| 1 | 5/27 | 200 | NULL | NULL |
| 1 | 5/26 | 300 | 10 | NULL |
| 1 | 5/25 | NULL | NULL | NULL |
| 1 | 5/24 | ... | 20 | NULL |
| 1 | 5/23 | ... | .... | 50 |
| 1 | 5/22 | ... | .... | 30 |
| 1 | 5/21 | ... | .... | NULL |
| 1 | 5/20 | ... | .... | ... |
| 1 | 5/19 | ... | .... | ... |
| 1 | 5/18 | ... | .... | ... |
| 1 | 5/17 | ... | .... | ... |
+------+-------+--------------------------------------+
我需要查询每列的最新可能值。因此,如果 value2 在 value3 不为 NULL 的那一天为 NULL,它将获取 value2 不为 null 的先前记录。我不确定这是否有意义,但这是结果 table 我想要的:
+------+-------+-------+--------+----------+
| id | date | value | value2 | value3 |
+------+-------+-------+--------+----------+
| 1 | 5/28 | 100 | 10 | 50 |
+------+-------+---------------------------+
日期永远是最新的(在这个例子中,它是 5/28)然后至于其余的,我需要为每一列获取最新的值,即使它与日期不匹配。
这可能吗?
这是一种选择:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test (datum, value1, value2, value3) as
2 (select date '2018-05-28', 100, null, null from dual union
3 select date '2018-05-27', 200, null, null from dual union
4 select date '2018-05-26', 300, 10, null from dual union
5 select date '2018-05-23', 500, null, 50 from dual
6 ),
7 inter as
8 (select
9 first_value(datum ignore nulls) over (order by datum desc) datum,
10 first_value(value1 ignore nulls) over (order by datum desc) value1,
11 first_value(value2 ignore nulls) over (order by datum desc) value2,
12 first_value(value3 ignore nulls) over (order by datum desc) value3
13 from test
14 order by 1 desc nulls last, 2 desc nulls last, 3 desc nulls last, 4 desc nulls last
15 )
16 select *
17 from inter
18 where rownum = 1;
DATUM VALUE1 VALUE2 VALUE3
---------- ---------- ---------- ----------
28.05.2018 100 10 50
SQL>
last_valuewindow函数也可以用于此。
示例:
create table test_table(id int, "date" date, value int, value2 int, value3 int);
insert into test_table (id, "date", value, value2, value3)
select 1, date '2018-05-28', 100, null, null from dual union
select 1, date '2018-05-27', 200, null, null from dual union
select 1, date '2018-05-26', 300, 10, null from dual union
select 1, date '2018-05-23', 500, null, 50 from dual;
insert into test_table (id, "date", value, value2, value3)
select 2, "date" + 1, value+100, value2+10, value3+10 from test_table;
select
id,
max("date") as "date",
max(lastValue1) as value,
max(lastValue2) as value2,
max(lastValue3) as value3
from
(
select id, "date",
last_value(value ignore nulls) over (partition by id order by "date" ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lastValue1,
last_value(value2 ignore nulls) over (partition by id order by "date" ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lastValue2,
last_value(value3 ignore nulls) over (partition by id order by "date" ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lastValue3
from test_table
) q
group by id;
ID | date | VALUE | VALUE2 | VALUE3
-- | --------- | ----- | ------ | ------
1 | 28-MAY-18 | 100 | 10 | 50
2 | 29-MAY-18 | 200 | 20 | 60
db<>fiddle here
我有这个table:
+------+-------+---------+----------------------------+
| id | date | value | value2 | value3 |
+------+-------+---------+----------------------------+
| 1 | 5/28 | 100 | NULL | NULL |
| 1 | 5/27 | 200 | NULL | NULL |
| 1 | 5/26 | 300 | 10 | NULL |
| 1 | 5/25 | NULL | NULL | NULL |
| 1 | 5/24 | ... | 20 | NULL |
| 1 | 5/23 | ... | .... | 50 |
| 1 | 5/22 | ... | .... | 30 |
| 1 | 5/21 | ... | .... | NULL |
| 1 | 5/20 | ... | .... | ... |
| 1 | 5/19 | ... | .... | ... |
| 1 | 5/18 | ... | .... | ... |
| 1 | 5/17 | ... | .... | ... |
+------+-------+--------------------------------------+
我需要查询每列的最新可能值。因此,如果 value2 在 value3 不为 NULL 的那一天为 NULL,它将获取 value2 不为 null 的先前记录。我不确定这是否有意义,但这是结果 table 我想要的:
+------+-------+-------+--------+----------+
| id | date | value | value2 | value3 |
+------+-------+-------+--------+----------+
| 1 | 5/28 | 100 | 10 | 50 |
+------+-------+---------------------------+
日期永远是最新的(在这个例子中,它是 5/28)然后至于其余的,我需要为每一列获取最新的值,即使它与日期不匹配。
这可能吗?
这是一种选择:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test (datum, value1, value2, value3) as
2 (select date '2018-05-28', 100, null, null from dual union
3 select date '2018-05-27', 200, null, null from dual union
4 select date '2018-05-26', 300, 10, null from dual union
5 select date '2018-05-23', 500, null, 50 from dual
6 ),
7 inter as
8 (select
9 first_value(datum ignore nulls) over (order by datum desc) datum,
10 first_value(value1 ignore nulls) over (order by datum desc) value1,
11 first_value(value2 ignore nulls) over (order by datum desc) value2,
12 first_value(value3 ignore nulls) over (order by datum desc) value3
13 from test
14 order by 1 desc nulls last, 2 desc nulls last, 3 desc nulls last, 4 desc nulls last
15 )
16 select *
17 from inter
18 where rownum = 1;
DATUM VALUE1 VALUE2 VALUE3
---------- ---------- ---------- ----------
28.05.2018 100 10 50
SQL>
last_valuewindow函数也可以用于此。
示例:
create table test_table(id int, "date" date, value int, value2 int, value3 int);
insert into test_table (id, "date", value, value2, value3) select 1, date '2018-05-28', 100, null, null from dual union select 1, date '2018-05-27', 200, null, null from dual union select 1, date '2018-05-26', 300, 10, null from dual union select 1, date '2018-05-23', 500, null, 50 from dual;
insert into test_table (id, "date", value, value2, value3) select 2, "date" + 1, value+100, value2+10, value3+10 from test_table;
select id, max("date") as "date", max(lastValue1) as value, max(lastValue2) as value2, max(lastValue3) as value3 from ( select id, "date", last_value(value ignore nulls) over (partition by id order by "date" ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lastValue1, last_value(value2 ignore nulls) over (partition by id order by "date" ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lastValue2, last_value(value3 ignore nulls) over (partition by id order by "date" ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lastValue3 from test_table ) q group by id;
ID | date | VALUE | VALUE2 | VALUE3 -- | --------- | ----- | ------ | ------ 1 | 28-MAY-18 | 100 | 10 | 50 2 | 29-MAY-18 | 200 | 20 | 60
db<>fiddle here