将SQL中的记录与后续日期合并?

时间:2011-02-21 10:49:59

标签: sql postgresql date

我想使用sql合并以下数据:

no code area rate startdate enddate  
1  0101 EU   0.1% 20050101  20051231  
2  0101 EU   0.1% 20060101  20061231
3  0101 EU   0.1% 20080101  20081231  
4  0101 EFTA 0.2% 20050101  20051231  
5  0101 EFTA 0.1% 20060101  20061231  
  • 在上面的示例中,不应该合并1和2,因为它们具有相同的代码,相同的速率,具有后续日期并且来自同一区域。
  • 不应合并第3项,因为日期不是后续日期。
  • 4和5不应合并,因为它们的费率不同。

最终结果应如下所示:

no code area rate startdate enddate  
1  0101 EU   0.1% 20050101  20061231  
3  0101 EU   0.1% 20080101  20081231  
4  0101 EFTA 0.2% 20050101  20051231  
5  0101 EFTA 0.1% 20060101  20061231  

有没有办法只使用sql?我正在使用postgres。

由于

3 个答案:

答案 0 :(得分:1)

假设这是一个你想要做的一次性命中,并且不是一些正在进行的生产解决方案的一部分,我认为你要做到这一点的唯一方法是用光标。

我不知道Postgres,但似乎它们的游标与MS-Sql类似:http://www.postgresql.org/docs/current/static/plpgsql-cursors.html

游标允许您“循环”一个select语句,将值放入临时变量,然后您可以在其中处理它们。它更类似于程序编程。

性能不是很好,这就是为什么它可以作为一次性的事情,但如果你遇到性能问题,可能会有一个更复杂(但性能更高)的解决方案。

我首先创建一个游标来循环遍历表,将代码,rate,startdate和endate放入变量中。 (如果按代码,速率和开始日期对select语句进行排序,则可以保证所有记录都以正确的顺序出现。)对于每条记录,您可以将当前代码和速率与变量中的值进行比较,以及如果它们相同,则更新结束日期变量。

使用第二个表(或表变量)作为结果。如果代码/速率与变量不同,那么变量中的所有内容都是新的候选对象。写出来,然后用新数据更新变量并继续。

在一次通过中,您将创建新表。然后,您可以删除原始的并替换,或将其存储在其他位置。

答案 1 :(得分:0)

也许我错过了什么,但对我来说似乎你想要:

SELECT DISTINCT ON (code, area, rate, startdate, enddate), 
       no, 
       code, 
       area, 
       rate, 
       startdate, 
       enddate  
FROM your_table

答案 2 :(得分:0)

我遇到了同样的问题。我用它来划分' '组中的有序列表'具有后续日期的行,通过标记'组'的第一行('原始')行。这是一个不在其前身之后的那个,然后找到每个'组的列表行。 - 最后一行的结束日期是“汇总”和“#39;结束日期。

  1. 使用新列Subsequent(int)创建其他表。将原始表格中的所有行复制到这一个填充新列中的“后续”列中。如下:如果行的开始日期等于上一行的结束日期,则后续= 1(表示此行在前一行之后),如果不等于0,则表示该行开始新序列。为了找到上一行的结束日期,使用由代码和区域划分的lag()函数,并按开始日期排序。例如,在上面提到的示例中,行号为。 2将具有后续= 1并且所有其他后续= 0。

  2. 写一个查询,它将从上表中选择Subsequent = 0的行,即' original'对于每个选定的原始行,使用代码和速率,然后在原始行之后的所有后续行中查找最大结束日期。

  3. 可以使用以下子查询找到最大结束日期:

    (A)尝试在原始版本之后的后续行中找到它:

    从符合条件的所有行中选择最大结束日期:

    • 后续为1,即仅后续行
    • 代码等于原始行的代码
    • rate等于原始行的代码
    • 开始日期大于原始行的开始日期
    • 结束日期小于下一个原始行的开始日期,或者,如果没有下一个原始行,则结束日期=代码和费率组合的所有结束日期的最大值"

    另一个子查询可以找到下一个原始行:选择

    所有行
    • 后续= 0
    • 开始日期>原始行的开始日期
    • 代码和费率与原始行相同。

    (B)如果上面返回null,即原始行没有后续行,则该行的结束日期是它自己的结束日期。

    合并功能可以很好地在(A)和(B)之间做出选择。

    作为查询的结果,您应该有一个列表,您希望在示例中获得该列表。