选择 table 内的最新记录
Selecting the latest record within a table
我有一个 Oracle v11 数据库,虽然我没有 table 的模式定义,但我在下面说明了我想要实现的目标。
这就是 table 的样子
我正在尝试通过仅选择最新行来转换数据,table 保留更改历史记录,我对更改不感兴趣,只对每个当前问题的最新值感兴趣
这是我目前所拥有的。
select issueno,
case (when fieldname = 'name' then string_value end) name,
case (when fieldname = 'point' then string_value end) point
from issues
where issueno = 1234
上面查询的问题是它 return 有 4 行,我想 return 只有一行。
看看这样的事情是否有帮助;阅读代码中的注释。
SQL> with issues (issueno, fieldname, string_value,
2 transition_date, transition_id, load_date)
3 as
4 -- sample data; you have it in a table, don't type that
5 (select 1234, 'name', null , date '2021-01-01', 1, date '2021-01-02' from dual union all
6 select 1234, 'name', 'Tom', date '2021-02-11', 2, date '2021-02-12' from dual union all
7 select 1234, 'point', '0' , date '2021-02-04', 3, date '2021-02-05' from dual union all
8 select 1234, 'point', '5' , date '2021-02-10', 5, date '2021-02-11' from dual
9 ),
10 -- query you need begins here
11 temp as
12 -- rank values partitioned by ISSUENO and FIELDNAME, sorted by TRANSITION_ID
13 (select issueno, fieldname, string_value,
14 row_number() over (partition by issueno, fieldname
15 order by transition_id desc) rn
16 from issues
17 )
18 select issueno,
19 max(case when fieldname = 'name' then string_value end) name,
20 max(case when fieldname = 'point' then string_value end) point
21 from temp
22 where rn = 1
23 group by issueno;
ISSUENO NAME POINT
---------- ---------- ----------
1234 Tom 5
SQL>
您可以在 transition_date
(或 load_date
列的 MAX() KEEP (..)
值中使用 LAST ORDER BY
子句获取最新日期, 取决于哪个你的意思是在查询中替换) 例如
WITH i AS
(
SELECT CASE WHEN fieldname = 'name' THEN
MAX(string_value) KEEP (DENSE_RANK LAST ORDER BY transition_date)
OVER (PARTITION BY issue_no, fieldname)
END AS name,
CASE WHEN fieldname = 'point' THEN
MAX(string_value) KEEP (DENSE_RANK LAST ORDER BY transition_date)
OVER (PARTITION BY issue_no, fieldname)
END AS point
FROM issues
)
SELECT MAX(name) AS name, MAX(point) AS point
FROM i
但是,如果相关日期值出现平局(相等值),则考虑使用 DENSE_RANK()
函数来计算返回等于 1
以及 ROW_NUMBER()
以便能够在主查询中与 JOIN 子句一起使用,例如
WITH i AS
(
SELECT i.*,
DENSE_RANK() OVER ( PARTITION BY issue_no, fieldname
ORDER BY transition_date DESC) AS dr,
ROW_NUMBER() OVER ( PARTITION BY issue_no, fieldname
ORDER BY transition_date DESC) AS rn
FROM issues i
)
SELECT i1.string_value AS name, i2.string_value AS point
FROM ( SELECT string_value, rn FROM i WHERE dr = 1 AND fieldname = 'name' ) i1
FULL JOIN ( SELECT string_value, rn FROM i WHERE dr = 1 AND fieldname = 'point' ) i2
ON i2.rn = i1.rn
假设你想得到最新的记录load_date
select issueno,
case (when fieldname = 'name' then string_value end) name,
case (when fieldname = 'point' then string_value end) point
from issues
where issueno = 1234 and
(fieldname , load_date) in (select fieldname ,max(load_date) from issues where issueno=1234 group by fieldname)
我会使用子查询+window函数来实现你的要求(假设你使用的是基于load_date来确定最新记录)
select issueno,
case (when fieldname = 'name' then string_value end) name,
case (when fieldname = 'point' then string_value end) point
from
(
SELECT name, point, ROW_NUMBER() OVER(PARTITION BY ISSUENO, FIELDNAME ORDER BY LOAD_DATE DESC) RN
FROM issues
)
where issueno = 1234
AND RN = 1
语法 ROW_NUMBER() OVER ([query_partition_clause] order_by_clause)
实际上是一个 window 函数,它根据您在 [query_partition_clause] order_by_clause
中声明规则的方式为每一行分配排名
我有一个 Oracle v11 数据库,虽然我没有 table 的模式定义,但我在下面说明了我想要实现的目标。
这就是 table 的样子
我正在尝试通过仅选择最新行来转换数据,table 保留更改历史记录,我对更改不感兴趣,只对每个当前问题的最新值感兴趣
这是我目前所拥有的。
select issueno,
case (when fieldname = 'name' then string_value end) name,
case (when fieldname = 'point' then string_value end) point
from issues
where issueno = 1234
上面查询的问题是它 return 有 4 行,我想 return 只有一行。
看看这样的事情是否有帮助;阅读代码中的注释。
SQL> with issues (issueno, fieldname, string_value,
2 transition_date, transition_id, load_date)
3 as
4 -- sample data; you have it in a table, don't type that
5 (select 1234, 'name', null , date '2021-01-01', 1, date '2021-01-02' from dual union all
6 select 1234, 'name', 'Tom', date '2021-02-11', 2, date '2021-02-12' from dual union all
7 select 1234, 'point', '0' , date '2021-02-04', 3, date '2021-02-05' from dual union all
8 select 1234, 'point', '5' , date '2021-02-10', 5, date '2021-02-11' from dual
9 ),
10 -- query you need begins here
11 temp as
12 -- rank values partitioned by ISSUENO and FIELDNAME, sorted by TRANSITION_ID
13 (select issueno, fieldname, string_value,
14 row_number() over (partition by issueno, fieldname
15 order by transition_id desc) rn
16 from issues
17 )
18 select issueno,
19 max(case when fieldname = 'name' then string_value end) name,
20 max(case when fieldname = 'point' then string_value end) point
21 from temp
22 where rn = 1
23 group by issueno;
ISSUENO NAME POINT
---------- ---------- ----------
1234 Tom 5
SQL>
您可以在 transition_date
(或 load_date
列的 MAX() KEEP (..)
值中使用 LAST ORDER BY
子句获取最新日期, 取决于哪个你的意思是在查询中替换) 例如
WITH i AS
(
SELECT CASE WHEN fieldname = 'name' THEN
MAX(string_value) KEEP (DENSE_RANK LAST ORDER BY transition_date)
OVER (PARTITION BY issue_no, fieldname)
END AS name,
CASE WHEN fieldname = 'point' THEN
MAX(string_value) KEEP (DENSE_RANK LAST ORDER BY transition_date)
OVER (PARTITION BY issue_no, fieldname)
END AS point
FROM issues
)
SELECT MAX(name) AS name, MAX(point) AS point
FROM i
但是,如果相关日期值出现平局(相等值),则考虑使用 DENSE_RANK()
函数来计算返回等于 1
以及 ROW_NUMBER()
以便能够在主查询中与 JOIN 子句一起使用,例如
WITH i AS
(
SELECT i.*,
DENSE_RANK() OVER ( PARTITION BY issue_no, fieldname
ORDER BY transition_date DESC) AS dr,
ROW_NUMBER() OVER ( PARTITION BY issue_no, fieldname
ORDER BY transition_date DESC) AS rn
FROM issues i
)
SELECT i1.string_value AS name, i2.string_value AS point
FROM ( SELECT string_value, rn FROM i WHERE dr = 1 AND fieldname = 'name' ) i1
FULL JOIN ( SELECT string_value, rn FROM i WHERE dr = 1 AND fieldname = 'point' ) i2
ON i2.rn = i1.rn
假设你想得到最新的记录load_date
select issueno,
case (when fieldname = 'name' then string_value end) name,
case (when fieldname = 'point' then string_value end) point
from issues
where issueno = 1234 and
(fieldname , load_date) in (select fieldname ,max(load_date) from issues where issueno=1234 group by fieldname)
我会使用子查询+window函数来实现你的要求(假设你使用的是基于load_date来确定最新记录)
select issueno,
case (when fieldname = 'name' then string_value end) name,
case (when fieldname = 'point' then string_value end) point
from
(
SELECT name, point, ROW_NUMBER() OVER(PARTITION BY ISSUENO, FIELDNAME ORDER BY LOAD_DATE DESC) RN
FROM issues
)
where issueno = 1234
AND RN = 1
语法 ROW_NUMBER() OVER ([query_partition_clause] order_by_clause)
实际上是一个 window 函数,它根据您在 [query_partition_clause] order_by_clause