我有下表tbl_subscriptions。
+-----------+--------+----------+--------+
| Sub.Date | ID | POSITION | STATUS |
+-----------+--------+----------+--------+
| 8/22/2018 | 254515 | BROWN | OPEN |
| 8/21/2018 | 254515 | ORANGE | CLOSE |
| 8/20/2018 | 254515 | RED | CLOSE |
| 8/19/2018 | 254515 | ORANGE | CLOSE |
| 8/18/2018 | 254515 | BLUE | CLOSE |
| 8/17/2018 | 254515 | BLUE | CLOSE |
| 8/16/2018 | 254515 | BLUE | CLOSE |
| 8/15/2018 | 254515 | BLUE | CLOSE |
| 8/14/2018 | 254515 | ORANGE | CLOSE |
| 8/13/2018 | 254515 | BLUE | CLOSE |
+-----------+--------+----------+--------+
我真的很想了解以下内容。我有成千上万个带有各种ID的条目。 我需要获取所有“打开”条目以及最近从“蓝色”更改为“其他位置”的时间。参见下文,最近,头寸已于2018年8月19日从蓝色更改为橙色。所以,我想看这样的数据。
+-----------+--------+----------+--------+-----------------+
| Sub.Date | ID | POSITION | STATUS | Pos. Changed on |
+-----------+--------+----------+--------+-----------------+
| 8/22/2018 | 254515 | BROWN | OPEN | 8/19/2018 |
+-----------+--------+----------+--------+-----------------+
我什至不知道如何实现这一目标。使用Oracle查询至少可以做到这一点。
答案 0 :(得分:0)
您可以将lag
Windows功能用作:
select ttt.*,
(
select max(tt.sub_date)
from
(
select t.*,
lag(POSITION) over (partition by ID order by Sub_Date ) lg
from tab t
) tt
where STATUS != 'OPEN'
and tt.POSITION = 'ORANGE'
and tt.lg = 'BLUE'
) as changed_on
from tab ttt
where STATUS = 'OPEN';
答案 1 :(得分:0)
这是一种方法:
WITH your_table AS (SELECT to_date('22/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BROWN' position, 'OPEN' status FROM dual UNION ALL
SELECT to_date('21/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('20/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'RED' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('19/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('18/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('17/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('16/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('15/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('14/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('13/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('21/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BROWN' position, 'OPEN' status FROM dual UNION ALL
SELECT to_date('20/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('19/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'RED' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('18/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('17/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('16/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'OPEN' status FROM dual UNION ALL
SELECT to_date('15/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('14/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('13/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('12/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('29/08/2018', 'dd/mm/yyyy') sub_date, 1 ID, 'BLUE' position, 'OPEN' status FROM dual UNION ALL
SELECT to_date('28/08/2018', 'dd/mm/yyyy') sub_date, 1 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
SELECT to_date('27/08/2018', 'dd/mm/yyyy') sub_date, 1 ID, 'BLUE' position, 'OPEN' status FROM dual UNION ALL
SELECT to_date('26/08/2018', 'dd/mm/yyyy') sub_date, 1 ID, 'YELLOW' position, 'CLOSED' status FROM dual),
mid_res AS (SELECT sub_date,
ID,
position,
status,
CASE WHEN LAG(position) OVER (PARTITION BY ID ORDER BY sub_date) = 'BLUE' AND position != 'BLUE' THEN sub_date END blue_to_non_blue_dt
FROM your_table),
res AS (SELECT sub_date,
ID,
position,
status,
blue_to_non_blue_dt,
last_value(blue_to_non_blue_dt IGNORE NULLS) OVER (PARTITION BY ID ORDER BY sub_date) latest_blue_to_non_blue_dt
FROM mid_res)
SELECT sub_date,
ID,
position,
status,
latest_blue_to_non_blue_dt
FROM res
WHERE status = 'OPEN'
ORDER BY ID, sub_date DESC;
SUB_DATE ID POSITION STATUS LATEST_BLUE_TO_NON_BLUE_DT
----------- ---------- -------- ------ --------------------------
29/08/2018 1 BLUE OPEN
27/08/2018 1 BLUE OPEN
22/08/2018 254515 BROWN OPEN 19/08/2018
21/08/2018 254516 BROWN OPEN 18/08/2018
16/08/2018 254516 BLUE OPEN 13/08/2018
这是通过首先查找上一行为BLUE而当前行不是BLUE的行来实现的。然后,它会在随后的行中填充该值,然后最终进行过滤以仅显示打开的行。
我假设您可以为一个id拥有多个OPEN行,并且您希望每个OPEN行的最新更改日期,因此我添加了额外的示例数据来演示其外观(id的1和254516)。
答案 2 :(得分:0)
您可以仅使用窗口功能来完成此操作:
select t.*
from (select t.*,
max(case when position = 'ORANGE' and prev_position = 'BLUE' then sub_date end) over (partition by id) as change_date
from (select t.*,
lag(position) over (partition by ID order by sub_date) as prev_position
from t
) t
) t
where status = 'OPEN';