选择组中的最低行
Pick lowest row in a group
有 1 个 table,其中所有这些记录都是为 1 名员工维护的。由于此 table 中的多一列未在此示例中显示,因此该人甚至有 1 份工作有多行,即工作 J1 有 2 行,工作 J2 有 3 行,工作 J1 有 2 行,顺序为位置的方式相同。这个人从工作 J1 切换到 J2,然后又从 J1 切换到 location 。如何在发生切换时提取所需的行,因为当工作或位置发生变化时,我必须提取最少的每一行。请帮助我。
StDt EdDt Job Location Required_Rows
01-Jan-21 31-Jan-21 J1 L1 Y
01-Feb-21 30-Jun-21 J1 L1 N
01-Jul-21 30-Jul-21 J2 L1 Y
01-Aug-21 15-Aug-21 J2 L2 Y
16-Aug-21 31-Aug-21 J2 L2 N
01-Sep-21 01-Nov-21 J1 L2 Y
02-Nov-21 31-Dec-21 J1 L1 Y
这是一种方法,假设 table 被命名为 job_history
,它有一个额外的列 employee_id
,您需要查询一次为您提供所有员工的答案,并且您的 Oracle 版本至少为 12.1:
select *
from job_history
match_recognize(
partition by employee_id
order by stdt
all rows per match
pattern ( y {- n* -} )
define n as job = prev(job) and location = prev(location)
);
查询所做的只是根据您的定义将每一行“标记”(“分类”)为 Y 或 N,然后从输出中排除 N 行({- ... -}
的含义pattern
子句)。
如果您只需要为一名员工提供此功能,请添加 where
子句并删除 match_recognize
中的 partition by
子句,因为它不再需要了。
几乎是你的previous question的副本:
从 Oracle 12 开始,您可以使用 MATCH_RECOGNIZE
:
SELECT *
FROM table_name
MATCH_RECOGNIZE(
ORDER BY stDt
ALL ROWS PER MATCH
PATTERN (same {- same* -})
DEFINE
same AS FIRST(job) = job AND FIRST(location) = location
)
对于早期版本,您可以使用LAG
解析函数:
SELECT StDt,
EdDt,
Job,
location
FROM (
SELECT t.*,
LAG(job) OVER (ORDER BY StDt) AS prev_job,
LAG(location) OVER (ORDER BY StDt) AS prev_location
FROM table_name t
)
WHERE prev_job IS NULL
OR prev_job != job
OR prev_location IS NULL
OR prev_location != location;
其中,对于示例数据:
CREATE TABLE table_name (StDt, EdDt, Job, Location) AS
SELECT DATE '2021-01-01', DATE '2021-01-31', 'J1', 'L1' FROM DUAL UNION ALL
SELECT DATE '2021-02-01', DATE '2021-06-30', 'J1', 'L1' FROM DUAL UNION ALL
SELECT DATE '2021-07-01', DATE '2021-07-31', 'J2', 'L1' FROM DUAL UNION ALL
SELECT DATE '2021-08-01', DATE '2021-08-15', 'J2', 'L2' FROM DUAL UNION ALL
SELECT DATE '2021-08-16', DATE '2021-08-31', 'J2', 'L2' FROM DUAL UNION ALL
SELECT DATE '2021-09-01', DATE '2021-11-01', 'J1', 'L2' FROM DUAL UNION ALL
SELECT DATE '2021-11-01', DATE '2021-12-31', 'J1', 'L1' FROM DUAL
双输出:
STDT
EDDT
JOB
LOCATION
2021-01-01 00:00:00
2021-01-31 00:00:00
J1
L1
2021-07-01 00:00:00
2021-07-31 00:00:00
J2
L1
2021-08-01 00:00:00
2021-08-15 00:00:00
J2
L2
2021-09-01 00:00:00
2021-11-01 00:00:00
J1
L2
2021-11-01 00:00:00
2021-12-31 00:00:00
J1
L1
db<>fiddle here
有 1 个 table,其中所有这些记录都是为 1 名员工维护的。由于此 table 中的多一列未在此示例中显示,因此该人甚至有 1 份工作有多行,即工作 J1 有 2 行,工作 J2 有 3 行,工作 J1 有 2 行,顺序为位置的方式相同。这个人从工作 J1 切换到 J2,然后又从 J1 切换到 location 。如何在发生切换时提取所需的行,因为当工作或位置发生变化时,我必须提取最少的每一行。请帮助我。
StDt EdDt Job Location Required_Rows
01-Jan-21 31-Jan-21 J1 L1 Y
01-Feb-21 30-Jun-21 J1 L1 N
01-Jul-21 30-Jul-21 J2 L1 Y
01-Aug-21 15-Aug-21 J2 L2 Y
16-Aug-21 31-Aug-21 J2 L2 N
01-Sep-21 01-Nov-21 J1 L2 Y
02-Nov-21 31-Dec-21 J1 L1 Y
这是一种方法,假设 table 被命名为 job_history
,它有一个额外的列 employee_id
,您需要查询一次为您提供所有员工的答案,并且您的 Oracle 版本至少为 12.1:
select *
from job_history
match_recognize(
partition by employee_id
order by stdt
all rows per match
pattern ( y {- n* -} )
define n as job = prev(job) and location = prev(location)
);
查询所做的只是根据您的定义将每一行“标记”(“分类”)为 Y 或 N,然后从输出中排除 N 行({- ... -}
的含义pattern
子句)。
如果您只需要为一名员工提供此功能,请添加 where
子句并删除 match_recognize
中的 partition by
子句,因为它不再需要了。
几乎是你的previous question的副本:
从 Oracle 12 开始,您可以使用 MATCH_RECOGNIZE
:
SELECT *
FROM table_name
MATCH_RECOGNIZE(
ORDER BY stDt
ALL ROWS PER MATCH
PATTERN (same {- same* -})
DEFINE
same AS FIRST(job) = job AND FIRST(location) = location
)
对于早期版本,您可以使用LAG
解析函数:
SELECT StDt,
EdDt,
Job,
location
FROM (
SELECT t.*,
LAG(job) OVER (ORDER BY StDt) AS prev_job,
LAG(location) OVER (ORDER BY StDt) AS prev_location
FROM table_name t
)
WHERE prev_job IS NULL
OR prev_job != job
OR prev_location IS NULL
OR prev_location != location;
其中,对于示例数据:
CREATE TABLE table_name (StDt, EdDt, Job, Location) AS
SELECT DATE '2021-01-01', DATE '2021-01-31', 'J1', 'L1' FROM DUAL UNION ALL
SELECT DATE '2021-02-01', DATE '2021-06-30', 'J1', 'L1' FROM DUAL UNION ALL
SELECT DATE '2021-07-01', DATE '2021-07-31', 'J2', 'L1' FROM DUAL UNION ALL
SELECT DATE '2021-08-01', DATE '2021-08-15', 'J2', 'L2' FROM DUAL UNION ALL
SELECT DATE '2021-08-16', DATE '2021-08-31', 'J2', 'L2' FROM DUAL UNION ALL
SELECT DATE '2021-09-01', DATE '2021-11-01', 'J1', 'L2' FROM DUAL UNION ALL
SELECT DATE '2021-11-01', DATE '2021-12-31', 'J1', 'L1' FROM DUAL
双输出:
STDT EDDT JOB LOCATION 2021-01-01 00:00:00 2021-01-31 00:00:00 J1 L1 2021-07-01 00:00:00 2021-07-31 00:00:00 J2 L1 2021-08-01 00:00:00 2021-08-15 00:00:00 J2 L2 2021-09-01 00:00:00 2021-11-01 00:00:00 J1 L2 2021-11-01 00:00:00 2021-12-31 00:00:00 J1 L1
db<>fiddle here