Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 按值对有序表中的值更改进行间隔_Sql_Postgresql - Fatal编程技术网

Sql 按值对有序表中的值更改进行间隔

Sql 按值对有序表中的值更改进行间隔,sql,postgresql,Sql,Postgresql,我有一个使用PostgreSQL的特定任务,我需要一个SQL查询,但不幸的是,我无法得到正确的结果 我的表格示例如下: ---------------------------------------------- | ID | value | usage-date | ---------------------------------------------- | 1 | value1 | 2020-09-10 | --

我有一个使用PostgreSQL的特定任务,我需要一个SQL查询,但不幸的是,我无法得到正确的结果

我的表格示例如下:

----------------------------------------------
|    ID     |    value    |    usage-date    |
----------------------------------------------
|     1     |    value1   |    2020-09-10    |
----------------------------------------------
|     1     |    value1   |    2020-09-15    |
----------------------------------------------
|     1     |    value1   |    2020-09-20    |
----------------------------------------------
|     1     |    value1   |    2020-09-23    |
----------------------------------------------
|     1     |    value1   |    2020-09-25    |
----------------------------------------------
|     1     |    value1   |    2020-09-30    |
----------------------------------------------
|     1     |    value2   |    2020-09-15    |
----------------------------------------------
|     1     |    value2   |    2020-09-20    |
----------------------------------------------
|     1     |    value2   |    2020-09-23    |
----------------------------------------------
|     1     |    value2   |    2020-09-25    |
----------------------------------------------
因此,表是按ID、值和使用日期排序的。我的任务是提取时间间隔,这些时间间隔应该能够告诉您某个值从哪个日期到哪个日期处于活动状态。因此,输出如下所示:

--------------------------------------------------------------
|    ID     |    value    |    start-date    |    end-date   |
--------------------------------------------------------------
|     1     |    value1   |    2020-09-10    |   2020-09-15  |
--------------------------------------------------------------
|     1     |    value2   |    2020-09-15    |   2020-09-20  |
--------------------------------------------------------------
|     1     |    value1   |    2020-09-20    |   2020-09-23  |
--------------------------------------------------------------
|     1     |    value2   |    2020-09-23    |   2020-09-25  |
--------------------------------------------------------------
|     1     |    value1   |    2020-09-25    |   2020-09-30  |
--------------------------------------------------------------
有人知道怎么做吗

这是一个很好的例子,任何人都可以试试。

我猜,您的示例中有两行,一行表示活动的“开始”,另一行表示活动的“结束”。因为您没有显示任何其他标识符,所以查询比必须的复杂。因此,我们首先必须手动删除“end”行

SELECT
    id,
    value,
    usagedate,
    COALESCE(                                                                   -- 4
        lead(usagedate) OVER (PARTITION BY id ORDER BY usagedate),              -- 3
        first_value                                                             -- 4
    )
FROM (
    SELECT 
        *, 
        row_number() OVER (PARTITION BY id, value ORDER BY usagedate),          -- 1
        first_value(usagedate) OVER (PARTITION BY id ORDER BY usagedate DESC)   -- 2
    FROM
        t
)s
WHERE row_number % 2 = 1                                                        -- 1
  • 向表中添加行计数和标识符。这样做的目的是在以后删除每一行(“结束”记录)。这可以由
  • 我们需要保留最后的日期值(稍后需要)。这可以通过按降序获取第一个值(=按正常升序获取的最后一个值)来实现。这里我们也使用了一个适当的窗口函数
  • 删除第二行后(请参见
    WHERE
    子句),我们可以使用
    lead()
    窗口函数将每个已排序的下一行的值转换为当前行。因此,我们可以使用每个新活动的开始日期作为当前活动的结束日期。这就是为什么实际上您不需要“end”行,而我们删除了它们
  • 只有最后的记录才会出问题。由于上一条记录之后没有下一条记录,
    lead()
    函数返回
    NULL
    。为了避免这种情况,我们先前获取了最后一条记录(最后一个活动的结束)。使用
    COALESCE()
    函数可以实现这一点。它接受其参数列表中的第一个非空值,如果不是最后一个,则为
    lead
    值,如果是
    first\u值

  • 您的输入与预期的输出不一致,在预期的日期范围内,值1和值2之间没有明显的区别,似乎您只是想强制输出

    回答:如果您希望该值的日期范围接近,可以使用以下查询,而不是为每个值创建多个条目:

      select distinct one1.id,  vals.value1, one.minn as start_date, two.maxx as end_date from 
       table one1 inner join 
        (select value1 vals, min(user_date) as minn from table group by value1) one 
        on 
    one1.value = one.vals
    inner join (
        select value1 valm, max(user_date) as maxx from table group by value1) two 
        on one.vals = two.valm