当记录相对于多列(时间,连续,类别)相等或“接近”时,如何汇总记录?

时间:2019-07-07 10:14:13

标签: sql time-series amazon-redshift

上下文

我正在尝试根据给定的海平面和一些海平面B i 拍摄的照片数量(1 <= i <= N,N个海滩数量)的变化B i 特有的功能。

海平面随时间变化,这在数据库中由两个时间戳指示:start_datetime和end_datetime。我可以考虑10多个原因(source_id)来更改它,包括:

  • SENSOR:发送新测量值的传感器(只要海平面发生变化,它就可以是相对随机的;
  • 船:一条船刚刚靠近传感器,从而提高了水准。

我想避免在同一海平面上有200条连续记录,因为当我内部连接到包含已拍摄照片的表时(为了在没有任何照片的时间间隔内没有600M +条记录) ,很多短记录将被删除,而如果将它们汇总在一起,它们的间隔将更长,并且大多数匹配记录的照片,因此不会被删除。

我在哪里

  • 我考虑过使用STDDEV窗口功能,但是我不知道如何选择相关的动态窗口大小。
  • 我曾考虑过计算每个相邻记录之间的增量变化,但是我不想汇总从0到1000的记录(以0.1为步长)。

示例

案例1:SOURCE_ID相同,时间连续,海平面发生微小变化

我想汇总相对于第一个海平面值(此处为1732)(在时间上相邻)({第i 行的开始时间} = {第i-1 th 行的end_datetime} + -2秒),并且来自同一source_id。从这里开始:

| start_datetime | end_datetime  | sea_level | source_id |
|----------------|---------------|-----------|-----------|
| 4/30/19 20:15  | 4/30/19 21:36 | 1731      | SENSOR    |
| 4/30/19 19:52  | 4/30/19 20:15 | 1734      | SENSOR    |
| 4/30/19 19:29  | 4/30/19 19:52 | 1731      | SENSOR    |
| 4/30/19 19:20  | 4/30/19 19:29 | 1732      | SENSOR    |
| 4/30/19 18:32  | 4/30/19 19:20 | 1734      | SENSOR    |
| 4/30/19 18:22  | 4/30/19 18:32 | 1732      | SENSOR    |
| 4/30/19 18:04  | 4/30/19 18:22 | 1734      | SENSOR    |
| 4/30/19 17:49  | 4/30/19 18:04 | 1731      | SENSOR    |
| 4/30/19 17:31  | 4/30/19 17:49 | 1734      | SENSOR    |
| 4/30/19 17:22  | 4/30/19 17:31 | 1732      | SENSOR    |
| 4/30/19 16:53  | 4/30/19 17:22 | 1734      | SENSOR    |
| 4/30/19 16:39  | 4/30/19 16:53 | 1731      | SENSOR    |
| 4/30/19 16:16  | 4/30/19 16:39 | 1734      | SENSOR    |
| 4/30/19 16:09  | 4/30/19 16:16 | 1731      | SENSOR    |
| 4/30/19 15:24  | 4/30/19 16:09 | 1734      | SENSOR    |
| 4/30/19 15:07  | 4/30/19 15:24 | 1732      | SENSOR    | 1st value

要汇总到此:

| start_datetime | end_datetime  | sea_level | source_id |
|----------------|---------------|-----------|-----------|
| 4/30/19 15:07  | 4/30/19 21:36 | 1732      | SENSOR    | 1732 = AVG(AGG RECORDS)

案例2:更改SOURCE_ID

如果有一个不同的source_id,而与海平面的变化无关,我想保持这种差异,从此出发:

| start_datetime| end_datetime  | sea_level | source_id |
|---------------|---------------|-----------|-----------|
| 4/20/19 7:26  | 4/20/19 7:32  | 1732      | SENSOR    |°
| 4/20/19 7:19  | 4/20/19 7:26  | 1734      | SENSOR    |°
| 4/20/19 7:10  | 4/20/19 7:19  | 1731      | SENSOR    |°
| 4/20/19 6:47  | 4/20/19 7:10  | 1732      | SENSOR    |°
| 4/20/19 6:11  | 4/20/19 6:47  | 1731      | SENSOR    |°
| 4/20/19 5:54  | 4/20/19 6:11  | 1732      | SENSOR    |°
| 4/20/19 5:49  | 4/20/19 5:54  | 1734      | SENSOR    |°
| 4/20/19 5:37  | 4/20/19 5:49  | 1732      | SENSOR    |°
| 4/20/19 5:23  | 4/20/19 5:37  | 1731      | SENSOR    |°
| 4/20/19 5:04  | 4/20/19 5:23  | 1734      | SENSOR    |°
| 4/19/19 23:22 | 4/20/19 5:04  | 1968      | BOAT      | ***
| 4/19/19 23:05 | 4/19/19 23:22 | 1731      | SENSOR    |o
| 4/19/19 23:00 | 4/19/19 23:05 | 1732      | SENSOR    |o
| 4/19/19 22:49 | 4/19/19 23:00 | 1734      | SENSOR    |o
| 4/19/19 22:38 | 4/19/19 22:49 | 1731      | SENSOR    |o
| 4/19/19 22:32 | 4/19/19 22:38 | 1734      | SENSOR    |o
| 4/19/19 22:25 | 4/19/19 22:32 | 1731      | SENSOR    |o

要汇总到此:

| start_datetime| end_datetime  | sea_level | source_id |
|---------------|---------------|-----------|-----------|
| 4/20/19 5:04  | 4/20/19 7:32  | 1734      | SENSOR    |°
| 4/19/19 23:22 | 4/20/19 5:04  | 1968      | BOAT      | ***
| 4/19/19 22:25 | 4/19/19 23:22 | 1733      | SENSOR    |o

情况3:SOURCE_ID相同,但变化很大

如果更改的原因相同,但是其中一个(或多个)更改超过+ -1%更改,则我不希望将其与其他记录进行汇总,例如:

| start_datetime | end_datetime  | sea_level | source_id |
|----------------|---------------|-----------|-----------|
| 4/20/19 12:23  | 4/20/19 12:37 | 1731      | SENSOR    |°
| 4/20/19 12:10  | 4/20/19 12:23 | 1732      | SENSOR    |°
| 4/20/19 11:49  | 4/20/19 12:10 | 1734      | SENSOR    |°
| 4/20/19 11:43  | 4/20/19 11:49 | 1731      | SENSOR    |°
| 4/20/19 11:36  | 4/20/19 11:43 | 1734      | SENSOR    |°
| 4/20/19 11:31  | 4/20/19 11:36 | 1732      | SENSOR    |°
| 4/20/19 11:25  | 4/20/19 11:31 | 1910      | SENSOR    | ***
| 4/20/19 11:18  | 4/20/19 11:25 | 1911      | SENSOR    | ***
| 4/20/19 11:11  | 4/20/19 11:18 | 1910      | SENSOR    | ***
| 4/20/19 11:03  | 4/20/19 11:11 | 1912      | SENSOR    | ***
| 4/20/19 10:55  | 4/20/19 11:03 | 1732      | SENSOR    |o
| 4/20/19 10:49  | 4/20/19 10:55 | 1731      | SENSOR    |o
| 4/20/19 10:35  | 4/20/19 10:49 | 1734      | SENSOR    |o
| 4/20/19 10:27  | 4/20/19 10:35 | 1731      | SENSOR    |o
| 4/20/19 10:19  | 4/20/19 10:27 | 1734      | SENSOR    |o

成为这个:

| start_datetime | end_datetime  | sea_level | source_id |
|----------------|---------------|-----------|-----------|
| 4/20/19 11:31  | 4/20/19 12:37 | 1732      | SENSOR    |°
| 4/20/19 11:03  | 4/20/19 11:31 | 1911      | SENSOR    | ***
| 4/20/19 10:19  | 4/20/19 11:03 | 1733      | SENSOR    |o

2 个答案:

答案 0 :(得分:1)

不幸的是,在SQL中完全无法执行所需的操作。问题是当逐渐变化超过1%时。也就是说,一系列值如:

  • 1732
  • 1742
  • 1752
  • 1762

无差异为1%,但基于第一个值的总差异为1%。如果不查看所有先前的数据,就无法轻易确定新组将从何处开始。

某些数据库支持递归CTE,这些CTE允许逻辑位于数据库中。 Redshift不是其中之一。而且,递归CTE本质上只是稍微更有效的RBAR计算(逐行执行)。

也就是说,我不确定这是否对您造成重大影响(您的三个示例中都没有)。让我们忽略渐变的更改,并根据以下内容查找更改的时间段:

  • 源更改
  • 相邻记录之间的跳转幅度超过1%

使用class ExpansionBayCell { .... override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) self.checkBox.isChecked = self.isSelected } } 和累加的总和,这可以解决空白问题。

func btnDonePressed() {        
    guard let indexPaths = tableView.indexPathsForSelectedRows else {
        btnBackPressed()            
        return
    }

    let items = indexPaths.map { self.listItems[$0.row] }
    completion(items)
    btnBackPressed()
}

最里面的子查询获取以前的传感器和海平面信息。这用于确定组的起始位置。中间子查询中的累积和基于每个记录的开始累积和分配一个组ID。

最后,外部查询汇总该值。

答案 1 :(得分:0)

这看上去真像救援的WINDOW FUNCTIONS。您可以找到上一个结束日期和下一个开始日期之间的差异,如下所示:

SELECT TOP 10 *, DATEDIFF(SECOND, end_datetime, LEAD(start_datetime, 1) OVER (ORDER BY start_datetime)) [RecordDifference],
LEAD(sea_level,1) OVER (ORDER BY start_datetime) [NextSeaLevel]
FROM <YOUR_TABLE_NAME_HERE>

完成后,您可以按GROUP BY进行汇总:

SELECT MIN(start_datetime) [start_datetime], MAX(end_datetime) [end_datetime], [RecordDifference]
FROM
(
    SELECT start_datetime, end_datetime, sea_level, DATEDIFF(SECOND, end_datetime, LEAD(start_datetime, 1) OVER (ORDER BY start_datetime)) [RecordDifference]
    FROM <YOUR_TABLE_NAME_HERE>
) [rawData]
GROUP BY [RecordDifference]

您可以了解有关窗口功能here的更多信息。

作为记录,这是SQL Server语法,但与RedShift非常相似。