选择组中的最低行

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