Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL-如何选择具有相同值的第一个连续组_Sql_Postgresql_Gaps And Islands - Fatal编程技术网

PostgreSQL-如何选择具有相同值的第一个连续组

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列的表:

我需要选择第一个连续组,即表按主键排序时,第一个连续组中所有行都具有相同的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);