如何使用 window 函数仅在 POSTGRES 中 select 行达到特定值
How to select rows up to a certain value only in POSTGRES using window function
我有以下 table 命名测试,并且只想 select 它到 1st 相同 ID 删除语句上方的行('1144QQT')。所以,从 2021-03-01 到 2021-06-02(只有粗体)。因此,这排除了带有 delete 语句的行。它确实包括更多不同类型的 ID 和更多相同类型的 ID。
Table 架构:
CREATE TABLE test(
id BIGINT PRIMARY KEY NOT NULL,
barcode_id VARCHAR NOT NULL,
date DATE NOT NULL,
keyword VARCHAR NOT NULL
);
INSERT INTO test
VALUES
(1, '1144QQT', '2021-03-01'::date, 'insert'),
(2, '1144QQT', '2021-03-01'::date, 'insert'),
(3, '1144QQT', '2021-03-01'::date, 'insert'),
(4, '1144QQT', '2021-03-01'::date, 'insert'),
(5, '1144QQT', '2021-03-01'::date, 'insert'),
(6, '1144QQT', '2021-03-01'::date, 'insert'),
(7, '1144QQT', '2021-03-01'::date, 'insert'),
(8, '1144QQT', '2021-03-01'::date, 'insert'),
(9, '1144QQT', '2021-03-01'::date, 'insert'),
(10, '1144QQT', '2021-03-01'::date, 'insert'),
(11, '1144QQT', '2021-03-01'::date, 'insert');
id
barcode_id
date
keyword
1
1144QQT
2021-03-01
insert
2
1144QQT
2021-03-02
adjust
3
5588aTT
2021-03-03
delete
4
4477aTT
2021-03-04
adjust
5
5588aTT
2021-03-05
adjust
6
1144QQT
2021-03-06
adjust
7
1144QQT
2021-03-07
delete
8
1144QQT
2021-03-08
insert
9
1144QQT
2021-03-09
adjust
10
1144QQT
2021-03-10
delete
11
4477aTT
2021-03-11
delete
所以,我期望的输出是这样的:
id
barcode_id
date
keyword
1
1144QQT
2021-03-01
insert
2
1144QQT
2021-03-02
adjust
6
1144QQT
2021-03-06
adjust
我如何使用 postgres 执行此操作?是否可以使用 window 函数来做到这一点?
根据您的描述,此逻辑似乎符合您的要求:
select t.*
from t
where t.id = '1144QQT' and t.keyword <> 'delete';
这假设删除后没有 id 的行 -- 但这似乎是合理的,并且与您的样本数据一致。
对于您的具体问题,一种方法是相关子查询:
select t.*
from t
where t.id = '1144QQT' and
t.id < (select min(t2.date)
from t t2
where t2.id = t.id and
t2.keyword <> 'delete'
);
以上版本version要求有一个“delete”——根据你的问题不清楚是否有要求。另一种方法是使用 window 函数:
select t.*
from (select t.*,
min(date) filter (where keyword = 'delete') over (partition by id) as min_delete_date
where t.id = '1144QQT'
) t
where date < min_delete_date;
如果你想要所有的行,如果没有“删除”,那么在外where
.
上添加or min_delete_date is null
使用SUM()
window函数识别第一行之前的行 keyword = 'delete'
:
SELECT id, date, keyword
FROM (
SELECT *, SUM((keyword = 'delete')::int) OVER (ORDER BY date) grp
FROM tablename
WHERE id = '1144QQT'
) t
WHERE grp = 0
参见demo。
结果:
id
date
keyword
1144QQT
2021-03-01 00:00:00
insert
1144QQT
2021-03-02 00:00:00
adjust
1144QQT
2021-03-06 00:00:00
adjust
I just want to Select it up to row above the 1st delete statement of the same id.
NOT EXISTS()
救援:(注意 date
是一个 保留字 ,并且是列的错误名称)
SELECT *
FROM ztable zt
WHERE zt.zid = '1144QQT'
AND NOT EXISTS (
SELECT * FROM ztable nx
WHERE nx.zid = zt.zid
AND nx.zkeyword = 'delete'
AND nx.zdate <= zt.zdate
);
我有以下 table 命名测试,并且只想 select 它到 1st 相同 ID 删除语句上方的行('1144QQT')。所以,从 2021-03-01 到 2021-06-02(只有粗体)。因此,这排除了带有 delete 语句的行。它确实包括更多不同类型的 ID 和更多相同类型的 ID。
Table 架构:
CREATE TABLE test(
id BIGINT PRIMARY KEY NOT NULL,
barcode_id VARCHAR NOT NULL,
date DATE NOT NULL,
keyword VARCHAR NOT NULL
);
INSERT INTO test
VALUES
(1, '1144QQT', '2021-03-01'::date, 'insert'),
(2, '1144QQT', '2021-03-01'::date, 'insert'),
(3, '1144QQT', '2021-03-01'::date, 'insert'),
(4, '1144QQT', '2021-03-01'::date, 'insert'),
(5, '1144QQT', '2021-03-01'::date, 'insert'),
(6, '1144QQT', '2021-03-01'::date, 'insert'),
(7, '1144QQT', '2021-03-01'::date, 'insert'),
(8, '1144QQT', '2021-03-01'::date, 'insert'),
(9, '1144QQT', '2021-03-01'::date, 'insert'),
(10, '1144QQT', '2021-03-01'::date, 'insert'),
(11, '1144QQT', '2021-03-01'::date, 'insert');
id | barcode_id | date | keyword |
---|---|---|---|
1 | 1144QQT | 2021-03-01 | insert |
2 | 1144QQT | 2021-03-02 | adjust |
3 | 5588aTT | 2021-03-03 | delete |
4 | 4477aTT | 2021-03-04 | adjust |
5 | 5588aTT | 2021-03-05 | adjust |
6 | 1144QQT | 2021-03-06 | adjust |
7 | 1144QQT | 2021-03-07 | delete |
8 | 1144QQT | 2021-03-08 | insert |
9 | 1144QQT | 2021-03-09 | adjust |
10 | 1144QQT | 2021-03-10 | delete |
11 | 4477aTT | 2021-03-11 | delete |
所以,我期望的输出是这样的:
id | barcode_id | date | keyword |
---|---|---|---|
1 | 1144QQT | 2021-03-01 | insert |
2 | 1144QQT | 2021-03-02 | adjust |
6 | 1144QQT | 2021-03-06 | adjust |
我如何使用 postgres 执行此操作?是否可以使用 window 函数来做到这一点?
根据您的描述,此逻辑似乎符合您的要求:
select t.*
from t
where t.id = '1144QQT' and t.keyword <> 'delete';
这假设删除后没有 id 的行 -- 但这似乎是合理的,并且与您的样本数据一致。
对于您的具体问题,一种方法是相关子查询:
select t.*
from t
where t.id = '1144QQT' and
t.id < (select min(t2.date)
from t t2
where t2.id = t.id and
t2.keyword <> 'delete'
);
以上版本version要求有一个“delete”——根据你的问题不清楚是否有要求。另一种方法是使用 window 函数:
select t.*
from (select t.*,
min(date) filter (where keyword = 'delete') over (partition by id) as min_delete_date
where t.id = '1144QQT'
) t
where date < min_delete_date;
如果你想要所有的行,如果没有“删除”,那么在外where
.
or min_delete_date is null
使用SUM()
window函数识别第一行之前的行 keyword = 'delete'
:
SELECT id, date, keyword
FROM (
SELECT *, SUM((keyword = 'delete')::int) OVER (ORDER BY date) grp
FROM tablename
WHERE id = '1144QQT'
) t
WHERE grp = 0
参见demo。
结果:
id | date | keyword |
---|---|---|
1144QQT | 2021-03-01 00:00:00 | insert |
1144QQT | 2021-03-02 00:00:00 | adjust |
1144QQT | 2021-03-06 00:00:00 | adjust |
I just want to Select it up to row above the 1st delete statement of the same id.
NOT EXISTS()
救援:(注意 date
是一个 保留字 ,并且是列的错误名称)
SELECT *
FROM ztable zt
WHERE zt.zid = '1144QQT'
AND NOT EXISTS (
SELECT * FROM ztable nx
WHERE nx.zid = zt.zid
AND nx.zkeyword = 'delete'
AND nx.zdate <= zt.zdate
);