如何保存 sql 中的最后一个检查点以用于下一行

How to save the last checkpoint in the sql to be used for next row

有什么方法可以存储最后一次迭代的行结果并将其用于下一行迭代?

例如我有一个 table say(Time_Table).

__   Key   type   timeStamp             
1 )    1     B    2015-06-28 09:00:00  
2 )    1     B    2015-06-28 10:00:00  
3 )    1     C    2015-06-28 11:00:00  
4 )    1     A    2015-06-28 12:00:00  
5 )    1     B    2015-06-28 13:00:00  

现在假设我有 90 分钟的 exceptionTime,这是恒定的。 如果我开始检查我的 Time_Table 那么:

  1. 第一行,因为09:00:00,之前没有行所以直接把这条记录放入我的目标table。现在我的参考点是 9:00:00.

  2. 对于 10:00:00, 的第二行,最后一个参考点是 09:00:00 并且 TIMESTAMPDIFF(s,09:00:00,10:00:00) 是 60,小于要求的 90。我不添加这一行到我的目标 table.

  3. 对于第三行,最后记录的异常是在09:00:00,而TIMESTAMPDIFF(s,09:00:00,11:00:00)是120,大于要求的90,所以我选择这条记录并设置参考指向 11:00:00.

  4. 为第四行TIMESTAMPDIFF(s,11:00:00,12:00:00)。同样不会保存。

  5. 这个又被保存了

目标table

__   Key   type   timeStamp             
1 )    1     B    2015-06-28 09:00:00  
2 )    1     C    2015-06-28 11:00:00   
3 )    1     B    2015-06-28 13:00:00 

有什么办法可以解决这个问题purely in SQL

我的做法:

SELECT * FROM Time_Table A WHERE NOT EXISTS(
       SELECT 1 FROM Time_Table B
       WHERE  A.timeStamp > B.timeStamp
       AND    abs(TIMESTAMPDIFF(s,B.timeStamp,A.timeStamp)) > 90 
)

但这实际上不起作用。

在 Vertica 中仅使用纯 SQL 是不可能的。要在纯 SQL 中执行此操作,您需要能够执行 Vertica 产品不支持的递归查询。在其他数据库产品中,您可以使用 WITH 子句来执行此操作。对于 Vertica,您将不得不在应用程序逻辑中执行此操作。这是基于来自 Vertica 7.1.x documentation

的声明 "Each WITH clause within a query block must have a unique name. Attempting to use same-name aliases for WITH clause query names within the same query block causes an error. WITH clauses do not support INSERT, DELETE, and UPDATE statements, and you cannot use them recursively"

绝对是,(不是纯 SQL)要么使用 LAG(since 7.1.x)取决于您使用的 Vertica 版本 或创建自定义 UDx(用户定义的扩展)

UDx in Java 访问前一行,其行为类似于 LAG,仅需一步(hastag # performance) (github full of udx examples)

public class UdxTestFactory extends AnalyticFunctionFactory {

    @Override
    public AnalyticFunction createAnalyticFunction(ServerInterface srvInterface) {
        return new Test();
    }

    @Override
    public void getPrototype(ServerInterface srvInterface, ColumnTypes argTypes,
                             ColumnTypes returnType) {
        argTypes.addInt();
        argTypes.addInt();
        returnType.addInt();
    }

    @Override
    public void getReturnType(ServerInterface srvInterface, SizedColumnTypes argTypes,
                              SizedColumnTypes returnType) throws UdfException {
        returnType.addInt();
    }

    private class Test extends AnalyticFunction {

        @Override
        public void processPartition(ServerInterface srvInterface, AnalyticPartitionReader inputReader, AnalyticPartitionWriter outputWriter)
                throws UdfException, DestroyInvocation {

            SizedColumnTypes inTypes = inputReader.getTypeMetaData();
            ArrayList<Integer> argCols = new ArrayList<Integer>();

            inTypes.getArgumentColumns(argCols);

            outputWriter.setLongNull(0);

            while (outputWriter.next()) {
                long v1 = inputReader.getLong(argCols.get(0)); // previous row
                inputReader.next();
                long v2 = inputReader.getLong(argCols.get(0)); // curent row
                outputWriter.setLong(0, v2 - v1);
            }
        }

    }


}

编译并将编译后的 类 合并到一个 jar 中,为简单起见将其命名为 TestLib.jar

$ javac -classpath /opt/vertica/bin/VerticaSDK.jar /opt/vertica/sdk/BuildInfo.java UdxTestFactory.java -d . 
$ jar -cvf TestLib.jar com/vertica/sdk/BuildInfo.class com/vertica/JavaLibs/*.class

加载库和函数

CREATE OR REPLACE LIBRARY TestFunctions AS '/home/dbadmin/TestLib.jar' LANGUAGE 'JAVA';
CREATE OR REPLACE ANALYTIC FUNCTION lag1 AS LANGUAGE 'java' NAME 'com.vertica.JavaLibs.UdxTestFactory' LIBRARY TestFunctions;

然后..使用它

SELECT 
    lag1(col1, null) OVER (ORDER BY col2) AS col1_minus_col2 
FROM ...