postgresql - 在两个特定行之间找到随机行,这些行遵循模式

时间:2017-04-27 10:34:04

标签: postgresql

抓我的头试图让它发挥作用。我有一个历史表,其中有一个帐户的多行(操作)。我知道特定操作之前和之后的模式,并希望查询以查找该表上所有帐户的操作。麻烦是我尝试过的所有东西都可以找到我想用作指导(前后)的动作,但不能找到中间的动作。

例如,这是一个帮助解释该场景的表格示例:

|action id |     comment     |  timestamp   |
|----------|-----------------|--------------|
|   0110   | random comment  |  timestamp 1 |
|   0117   | text pattern 1  |  timestamp 2 | 
|   0129   | RANDOM COMMENT  |  timestamp 3 |
|   0130   | text pattern 2  |  timestamp 4 |
|   0136   | random comment  |  timestamp 5 |
|   etc..  |                 |              |

因为你可以看到我必须使用的唯一一致模式是目标行之前和之后的文本模式(id 129)。我包括时间戳,因为我想也许可能会使用它?表上还有其他列,但它们基本上是随机的,并且用于此查询的目的不多。

关于如何实现这一目标的任何想法?

提前感谢任何建议,非常感谢。

我使用的代码不起作用:

select distinct ht.accountid, ht.id, ht.comment
  from historic_table ht 
 where ht.id > (select MAX(ht1.id) from historic_table ht1 where ht1.accountid = ht.accountid and ht1.comment ilike '%comment pattern 1%')
   and ht.id < (select MAX(ht2.id) from historic_table ht2 where ht2.accountid = ht.accountid and ht2.comment ilike '%comment pattern 2%')
 limit 10

这是我想要选择的输出示例。黄色是具有不同文本模式的前后行。在绿色中,我突出显示了我想在输出中看到的所有行。我只包括2个示例,其中一个具有1个目标行,另一个具有多个目标行。我希望这有助于澄清:

enter image description here

2 个答案:

答案 0 :(得分:1)

这不完美,不是最佳,但似乎有效。 CTE保证动作历史表只扫描一次,但由于// using a promise-enabled version of promise return request({ url: url, jar: new FileCookieStore(myfile) }); ,它仍然是顺序扫描。

如果历史相对稳定,我可能会将启动/停止记录的ID保存在(临时)表而不是CTE中。

注意:此解决方案假设记录正确排序(每个起始模式都正好一个匹配停止模式,他们不嵌套

ILIKE '% zzz%'

稍微修改过的版本,试图保持较小的CTE

CREATE TABLE zaction(
        id INTEGER NOT NULL PRIMARY KEY
        , zcomment text
        , ztimestamp timestamp NOT NULL
        );

INSERT INTO zaction(id, zcomment, ztimestamp) VALUES
 (   0110,      'random comment', '2017-04-27 12:00:00' )
,(   0117,      'text pattern 1', '2017-04-27 12:10:00' )
,(   0129,      'RANDOM COMMENT', '2017-04-27 12:20:00' )
,(   0130,      'text pattern 2', '2017-04-27 12:30:00' )
,(   0136,      'random comment', '2017-04-27 12:40:00' )
        --
,(   1110,      'random comment', '2017-04-27 12:00:00' )
,(   1117,      'text pattern 1', '2017-04-27 12:10:00' )
,(   1123,      'RANDOM COMMENT', '2017-04-27 12:20:00' )
,(   1129,      'RANDOM CONTENT', '2017-04-27 12:20:00' )
,(   1130,      'text pattern 2', '2017-04-27 12:30:00' )
,(   1136,      'random comment', '2017-04-27 12:40:00' )
        --
        ;

VACUUM ANALYZE zaction;


-- SELECT * FROM zaction;

EXPLAIN
WITH z1 AS (
        SELECT za.id
        , CASE WHEN zcomment ilike '%text pattern 1' THEN 1
             WHEN zcomment ilike '%text pattern 2' THEN -1
             ELSE 0 END AS dir
        FROM zaction za
        )
, z2 AS (
        SELECT z1.id, z1.dir
        , SUM(z1.dir) OVER (ORDER BY z1.id) AS yesno
        FROM z1
        )
SELECT za.*
FROM zaction za
JOIN z2 ON z2.id = za.id AND z2.yesno > 0 AND z2.dir = 0
        ;

答案 1 :(得分:0)

我设法得到了所需的结果,尽管使用string_agg来包含所有帐户的两个指定文本模式之间的所有操作ID和注释,但输出格式受到损害。将其发布在下面以防万一其他人可以使用它:

  select ht.accountid
        ,string_agg(ht.id::text, ', ') as actions_ids
        ,string_agg(ht.comment, ', ') as comments
    from historic_table ht 
   where ht.timestamp >= '2017-02-01'
     and ht.timestamp <  '2017-03-01'
     and ht.id > (select max(ht1.id) from historic_table ht1 where ht1.accountid = ht.accountid and ht1.comment ilike '%comment pattern 1%')
     and ht.id < (select max(ht2.id) from historic_table ht2 where ht2.accountid = ht.accountid and ht2.comment ilike '%comment pattern 2%')
group by ht.accountid
order by 1

具体来说,我必须删除distinct(我不需要它),这是导致崩溃的罪魁祸首我之前运行它(表格太大了,有许多自定义注释,不同的是试图排序/ unique整个结果集并重载存储在pg_temp中的数据)。通过添加时间戳过滤器并删除它,它实际上运行得非常快。