代码之家  ›  专栏  ›  技术社区  ›  bo-oz

如何从子查询中找到的一些潜在记录中选择最新记录

  •  0
  • bo-oz  · 技术社区  · 8 年前

    我有一张桌子,上面有顾客的同意记录。每次状态更改时,都会创建一个新记录。我试图确定在任何一个特定的日期是否有一个客户的同意。

    我从一个子查询开始是这样的:

    SELECT OPT_TYPE
    FROM CONSENTS C
    WHERE C.DATE < '20180101'
    

    问题是可能有多个记录符合这些条件。来自PostgreSQL的背景,我发现在Teradata中没有LIMIT 1选项是很奇怪的。所以,浏览手册我发现我可以使用合格的icw排名。所以我尝试将查询扩展到:

    SELECT OPT_TYPE
    FROM CONSENTS C
    WHERE C.DATE < '20180101'
    QUALIFY RANK() OVER (ORDER BY C.DATE) = 1
    

    不幸的是,这给了我一个语法错误 Syntax error: Order-based Aggregate and Ordered Analytical Functions are not allowed in subqueries. . 有谁能告诉我如何做到这一点?我知道这可能是一个Teradata noob问题,所以请原谅我。

    样本数据

    Date      Consent  Account_id
    20180201  Opt_out  1
    20171115  Opt_in   1
    20170307  Opt_out  1
    

    我想找到任何时间点的最新记录。所以如果我查询<20180101,它应该返回Opt_-in(记录2),如果我查询<20171010,它应该返回Opt_-out。

    2 回复  |  直到 8 年前
        1
  •  1
  •   Gordon Linoff    8 年前

    一种方法是:

    select c.*
    from consents c
    where c.date = (select max(c2.date)
                    from consents c2
                    where c2.date < '20180101'
                   );
    

    在较新版本中,您可以执行以下操作:

    SELECT TOP (1) OPT_TYPE
    FROM CONSENTS C
    WHERE C.DATE < '20180101'
    ORDER BY C.DATE DESC;
    
        2
  •  0
  •   dnoeth    8 年前

    子查询中不允许使用顶级OLAP函数,因为它可能是相关的子查询。

    作为解决方法,可以将其重写为联接,也可以将其嵌套在派生表中:

    select ...
    from mytable join
     (
       SELECT OPT_TYPE
       FROM CONSENTS C
       WHERE C.DATE < '20180101'
       QUALIFY RANK() OVER (ORDER BY C.DATE) = 1
     ) as dt
    on ... 
    
    select ...
    from ...
    where OPT_TYPE in
     ( 
       SELECT *
       FROM
        (
          SELECT OPT_TYPE
          FROM CONSENTS C
          WHERE C.DATE < '20180101'
          QUALIFY RANK() OVER (ORDER BY C.DATE) = 1
        ) as dt
     ) 
    

    顺便说一下,如果您的日期列实际上是一个日期,那么您应该使用 日期文字 DATE '2018-01-01' 而不是字符串 '20180101' .

    推荐文章