PostgreSQL-如何选择具有相同值的第一个连续组
我有一个包含pk和dept列的表: 我需要选择第一个连续组,即表按主键排序时,第一个连续组中所有行都具有相同的dept值,即预期结果为:PostgreSQL-如何选择具有相同值的第一个连续组,sql,postgresql,gaps-and-islands,Sql,Postgresql,Gaps And Islands,我有一个包含pk和dept列的表: 我需要选择第一个连续组,即表按主键排序时,第一个连续组中所有行都具有相同的dept值,即预期结果为: pk dept ------- 27 A 29 A 在我的示例中,有3个连续的组AA、BB和A。一个组的大小是无限的,可以超过2。我不确定我是否理解您的问题,但对于每个部门的第一个pk,您可以尝试以下方法: select min(pk) as pk, dept from your_table group by dept 记住存储函数。与使
pk dept
-------
27 A
29 A
在我的示例中,有3个连续的组AA、BB和A。一个组的大小是无限的,可以超过2。我不确定我是否理解您的问题,但对于每个部门的第一个pk,您可以尝试以下方法:
select min(pk) as pk,
dept
from your_table
group by dept
记住存储函数。与使用窗口函数不同,它允许避免读取整个表格:
--drop function if exists foo();
--drop table if exists t;
create table t(pk int, dep text);
insert into t values(27,'A'),(29,'A'),(30,'B'),(31,'B'),(33,'A');
create function foo() returns setof t language plpgsql as $$
declare
r t;
p t;
begin
for r in (select * from t order by pk) loop
if p is null then
p := r;
end if;
exit when p.dep is distinct from r.dep;
return next r;
end loop;
return;
end $$;
select * from foo();
它有点复杂,而且可能性能很差,但是您可以通过下面的代码实现您想要的。有四种操作: 第一个是我们获取基本顺序和基本组ID的地方 为下一次手术做准备。 在第二次操作中,我们将技巧计算为一个唯一的组 每个组的id 在第三个操作中,将唯一组id扩展到何处 每组的行。 最后,我们为每个组计算一个连续的组id以允许 群体的自由选择,所以我们只需通过 我们要获取的组号。 希望这有帮助
SELECT fourthOperation.pk,
fourthOperation.dept
FROM (SELECT thirdOperation.pk,
thirdOperation.dept,
DENSE_RANK() OVER (ORDER BY thirdOperation.spreadedIdGroup) denseIdGroup
FROM (SELECT secondOperation.*,
NVL(idGroup, LAG(secondOperation.idGroup IGNORE NULLS) OVER (ORDER BY secondOperation.numRow)) spreadedIdGroup
FROM (SELECT firstOperation.*,
CASE WHEN LAG(firstOperation.rankRow) OVER (ORDER BY firstOperation.numRow) = firstOperation.rankRow
THEN NULL
ELSE firstOperation.numRow
END idGroup
FROM (SELECT yourTable.*,
ROW_NUMBER() OVER (ORDER BY PK) AS numRow,
DENSE_RANK() OVER (ORDER BY DEPT) AS rankRow
FROM ABORRAR yourTable) firstOperation) secondOperation ) thirdOperation) fourthOperation
WHERE fourthOperation.denseIdGroup = 1
以下查询应执行我将您的表命名为tx所需的操作:
SELECT *
FROM tx t1
WHERE NOT EXISTS (
SELECT *
FROM tx t2
WHERE t2.dept <> t1.dept
AND t2.pk < t1.pk);
我们的想法是寻找元组,这样就不存在pk较小且部门不同的元组
保留前两个A元组;
由于前两个A元组,B元组被丢弃;
最后一个A元组由于B元组而被删除。
你已经把这个新的术语做了一组,你想要第一个,甚至用粗体写,但是我看不到一个定义。相应的组是由两条记录组成的集合,还是在主键发生变化之前至少由两条记录组成的集合,或者完全由其他内容组成的集合?第一个SELECT子句应该是SELECT PK,dept,而不是SELECT*;-除此之外,我同意有一点复杂的部分:D尽管有很好的SQL技能!我刚刚发现您的解决方案是错误的,因为它假定表是聚集在pk列上的。如果我添加一个元组1,'a',当op需要1、27和29时,您的解决方案将只检索该元组。感谢您的评论,但op表示表是按pk排序的,并且只需要第一个连续组,因此我的解决方案是正确的。此外,他想要整行,而不仅仅是pk。我不确定他是否认为表是在磁盘上排序的,没有最后一个WHERE子句,我得到1,'A',1,27,'A',2,30,'B',3,31,'B',3,33,'A',4,而我希望1,27和29在同一个denseidgroup中。。。我的意思是,除了pk和dept列Hanks Fabian供您更正之外,您还检索了一些denseIdGroup列,我做了一些更改以获得正确的结果集。基本上,我已经在第三个Operation LAG函数用法中包含了IGNORE NULLS子句,并用NVL替换CASE eval。此外,在第二个操作中,我将行为更改为仅在发生基于PK顺序的部门字段值更改的记录上分配组ID
SELECT *
FROM tx t1
WHERE NOT EXISTS (
SELECT *
FROM tx t2
WHERE t2.dept <> t1.dept
AND t2.pk < t1.pk);