0

我有一张表格widget_events,记录了小部件在 dateevent_what发生的事件。同一事件可能在同一天多次发生在同一个小部件上。出于这个原因,列被用作区分这些行的主键。这是表声明:widget_idevent_whenevent_id

CREATE TABLE widget_events
(
event_id    int4 UNIQUE NOT NULL,
event_when  date NOT NULL,
event_what  text NOT NULL,
widget_id   int4 REFERENCES widgets (widget_id) NOT NULL,
PRIMARY KEY (event_id)
);

客户端应用程序分批处理事件,其中每个批次包含一个小部件在一个日期的所有事件。但是,应用程序不知道哪些小部件和日期存储在widget_events.

一种可能的解决方案是首先从 widget_events(使用 SQL 的LIMIT)中选择一个随机行,然后对所有具有相同widget_idand的行进行另一次查询widget_when。处理完这个批次后,可以从 中删除这些行widget_events,我们回到第一步。当第一步报告没有更多随机行要返回时,算法停止。

我的问题是是否有更快、更优雅的方式来做到这一点。在 SQL(特别是 PostgreSQL 理解的 SQL)中是否可以在单个查询中返回每个不同的批次?

4

2 回答 2

3

要选择不同的批次:

select  distinct event_when
,       event_what
from    widget_events

或者您可以在一个查询中获取一个批次,例如:

select  batch.*
from    widget_events batch
join    (
        select  event_when
        ,       event_what
        from    widget_events
        limit   1
        ) filter
on      filter.event_when = batch.event_when
        and filter.event_what = batch.event_what
于 2012-12-03T15:35:33.583 回答
1

为什么不直接返回按 event_when 排序的行:

select *
from widget_events we
order by event_when, event_what, event_id

我也加入了 event_what,所以所有类似的事件都将出现在连续的行上。

然后,您的逻辑可以只查找日期何时更改以确定某事是否是最后一个事件。如果需要,您甚至可以将其放入选择中:

select *,
       (case when lag(event_when) over (partition by event_id) < event_when then 1
             else 0
        end) as isFirst,
       (case when lead(event_when) over (partition by event_id) < event_when then 1
             else 0
        end) as isLast
from widget_events we
order by event_when, event_what, event_id
于 2012-12-03T15:42:45.937 回答