【问题标题】:Select last inserted elements containing tags选择最后插入的包含标签的元素
【发布时间】:2021-03-12 11:25:53
【问题描述】:

我一直在努力从 PostgreSQL 获取一组数据。

我在 Docker 中使用 PostgreSQL 11,表 events 包含:

  Column   |    type   |   Modifiers
-----------|-----------|-------------
id         | text      | primary key
client_id  | text      | foreign key
created_at | timestamp | not null
context    | []text    | not null

目标是获取 client_id 子集的最后插入事件以及上下文子集。性能很重要,所以我只想使用 SQL。

到目前为止,我使用LATERAL 探索了一个解决方案,但它不能正常工作:

SELECT e2.*
FROM (
    SELECT events.client_id, events.context
    FROM events
    WHERE 
        events.client_id IN (?) AND
        events.context && ?
    GROUP BY (events.client_id, events.context)
) e1 LEFT JOIN LATERAL (
    SELECT *
    FROM events
    WHERE 
        events.client_id = e1.client_id AND
        events.context = e1.context
    ORDER BY events.created_at DESC LIMIT 1
) e2 ON true;

这样做的主要问题是,当给定的上下文文字出现在两个不同的上下文中时,此查询将返回两个事件,但我只想要一个。我希望 N 每 client_id 行,其中 N 介于 0(无事件)和参数中给定上下文的长度之间。


这些行的示例:

created_at      |  client_id   |  context
----------------| -------------|------------
5pm:15          |     accb     |  ['home']
5pm:15          |     baac     |  ['home']
5pm:20          |     accb     |  ['home','shopping_cart']
5pm:25          |     accb     |  ['shopping_cart','payment']
5pm:30          |     accb     |  ['disconnect']
5pm:30          |     baac     |  ['home','shopping_cart','payment']
5pm:35          |     baac     |  ['disconnect']

使用参数['accb','baac'] 用于客户端ID 和['home','shopping_cart'] 用于上下文,我想要结果:

created_at      |  client_id   |  context
----------------| -------------|------------
5pm:20          |     accb     |  ['home','shopping_cart']
5pm:25          |     accb     |  ['shopping_cart','payment']
5pm:30          |     baac     |  ['home','shopping_cart','payment']

你有什么解决办法吗?

【问题讨论】:

  • 样本数据和期望的结果会有所帮助。
  • 如何在上下文中为每个字面量确定要获取的行?例如。如果您有两行带有上下文['home', 'shopping_cart'] 和['home', 'shopping_cart', 'payment'] 并且您的过滤器是['shopping_cart', 'home'] 应该返回哪一个?问题不清楚。
  • 我想要参数中给出的每个client_id 和每个context 的最新events 行。两个参数都是数组。如果两个事件包含 ['home', 'shopping_cart'] 和 ['home', 'shopping_cart', 'payment'] 参数中带有 ['shopping_cart', 'home'] ,我想要这两个事件中最新的跨度>

标签: sql postgresql postgresql-11


【解决方案1】:

如果您希望每个client_id 有一行,我会推荐distinct on:

select distinct on (e.client_id) e.*
from events e
where e.client_id in (?) and
      e.context && ?
order by e.client_id, e.created_at desc;

【讨论】:

  • 不幸的是,我没有。我编辑了我的帖子,以便您获得更易于理解的解释
【解决方案2】:

一位同事找到了解决办法:

WITH ranked_events AS (
    SELECT
        events.*,
        ROW_NUMBER() OVER (PARTITION BY client_id ORDER BY created_at DESC) AS pos
    FROM
        events
    WHERE
        context @> ? AND
        client_id IN (?)
)
SELECT
    *
FROM
    ranked_events
WHERE
    pos = 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 2012-05-18
    • 2013-08-04
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多