在具有特定值

时间:2018-02-05 18:05:15

标签: sql postgresql window-functions gaps-and-islands

编辑2 当你拥有的是按count( <GROUP-START-COND> or null ) over ( order by <SORTING> ) AS groupnr排序的表时,记忆的解决方案为<SORTING>,新的行组由<GROUP-START-COND>发出信号,并且你需要一个随每组行增加的计数器,并在整个组中保持不变。

原始问题

给出一个这样的表:

╔════════╤═══════╤═══════╤════════════════════════════════════...
║ linenr │ level │  key  │ value                              ...
╠════════╪═══════╪═══════╪════════════════════════════════════...
║      9 │     1 │ title │ Text processing umbrella: Parse / T...
║     10 │     1 │ tags  │ text-processing typesetting markdow...
║     11 │     1 │ about │ unified is an interface for process...
║     12 │     2 │ ...   │ and rehype, but it also allows for ...
║     13 │     1 │ note  │ EXAMPLE                            ...
║     16 │     1 │ tags  │ foo bar baz                        ...
║     17 │     1 │ tags  │ ctx/tag spaceships/orville         ...
...

如何定义window,允许我array_agg对属于同一组的所有value进行注册,其中组被定义为具有相邻{{1}的行第一行包含linenrlevel = 1,以下行包含keylevel = 2(仅使用其中一个条件就足够了)。

我正在尝试提出一个涉及key = '...'的制剂但却陷入困境;可能首先对组进行编号,而对组编号进行聚合将是一个很好的解决方案。

编辑我意识到我的问题可能不是最清楚的,缺乏一个有效的例子,也许更好地发布到dba.stackexchange.com,所以在这里你可以参考改进的版本:

更新的问题

我有下表,数据如下所示; over ( ... rows between current row ... )是单调递增但不一定是连续的;当linenr字段包含省略号key时,表示从上方继续的条目:

...

现在我想要一个基于create table source ( linenr integer unique not null, key text not null, value text ); insert into source values ( 2, 'tags', 'a' ), ( 3, '...', 'b' ), ( 4, 'title', 'The Title' ), ( 5, 'note', 'this is' ), ( 6, '...', 'an EXAMPLE' ), ( 8, 'title', 'over' ), ( 9, '...', 'three' ), ( 10, '...', 'lines' ), ( 11, 'about', 'grouping' ); 字段内容分配组号的视图;组号不必是连续的,但对于以key以外的键开头的每组行应该是不同的,并且继续通过...key的所有行,如下所示:

...

我尝试用windows /分区和tabibitosan模式做到这一点,但是还没有能够提出任何工作;另外,如果有多个连续行╔════════╤═══════╤═══════╤════════════╗ ║ linenr │ group │ key │ value ║ ╠════════╪═══════╪═══════╪════════════╣ ║ 2 │ 1 │ tags │ a ║ ║ 3 │ 1 │ ... │ b ║ ║ 4 │ 2 │ title │ The Title ║ ║ 5 │ 3 │ note │ this is ║ ║ 6 │ 3 │ ... │ an EXAMPLE ║ ║ 8 │ 4 │ title │ over ║ ║ 9 │ 4 │ ... │ three ║ ║ 10 │ 4 │ ... │ lines ║ ║ 11 │ 5 │ about │ grouping ║ ╚════════╧═══════╧═══════╧════════════╝ ,则使用前一行lag()无效。在电子表格中,这是一件非常容易的事情,但在SQL中我似乎没有引用当前查询的前一行,可以吗?

讨论解决方案

原来有一个解决方案如此简单,它会伤害(不是自己想出来的):

...

这是有效的,因为我们为启动组的行分配select linenr as linenr, key as key, value as value, sum( rst ) over ( order by linenr ) as group_nr from ( select linenr, key, value, case when key != '...' then 1 end as rst from source ) as x; ,否则为1分配null。然后,sum()将所有行(按照正确的顺序)放在一起,将null视为零,然后使所有的组起始行获得新的group_id并进行所有后续操作行保持计数。如果你知道如何简单......

积分转到用户McNets

这同样可以通过一个简短且令人难忘的单行程来完成,其中请参阅上面的编辑和Erwin Brandstetter下面的答案。

编辑2 评论者理所当然地抱怨我编辑的问题确实是一个新问题。我认为结果是,当解决一个顽固的问题时,人们应该尝试找到那些不会转动的特殊螺钉,并提出一个小型模型,突出显示特定部分并省略其他部分。在这种情况下,聚合具有组号的行不是我的难点,它是分配组号;此外,“定义一个允许我对所有值进行array_aggregate的窗口”不是问题的一部分,它是我想象的可能导致解决方案的一部分。

2 个答案:

答案 0 :(得分:1)

回答更新(新)问题:

SELECT *
     , count(key <> '...' OR NULL) OVER (ORDER BY linenr) AS grp
FROM   source;

在dba.SE上看到dupe:

回答原始问题:

假设当前的Postgres 10和linenr被定义为UNIQUE,这将实现您的描述:

SELECT min(linenr) AS lines_from
     , max(linenr) AS lines_to
     , array_agg(value) AS value_arr
FROM  (
   SELECT linenr, level, value
        , count(level = 1 OR NULL) OVER (ORDER BY linenr) AS grp
        , row_number() OVER (ORDER BY linenr) - linenr    AS adjacent
   FROM   tbl
   ORDER  BY linenr
   ) sub
GROUP  BY grp, adjacent  -- same group, adjacent numbers
HAVING min(level) = 1    -- but only groups that start with level 1 
ORDER  BY lines_from;
带有扩展测试用例的

SQL Fiddle

相关,有更多解释:

关于count(level = 1 OR NULL)

答案 1 :(得分:0)

这可以使用Tabibitosan方法

完成
select array_agg(value) FROM
(
select t.*, row_number() OVER (ORDER BY linenr ) - 
       row_number() OVER (PARTITION BY CASE WHEN level = 2 and key = '...'
                          THEN 1 ELSE 0 END ORDER BY linenr ) as chg
FROM   Table1 as t
  ) as a 
  WHERE (level,key)  <> ( 2,'...')
  GROUP BY chg
  ORDER BY chg;