【问题标题】:nth result in Teradata result第 n 个结果为 Teradata 结果
【发布时间】:2011-03-13 22:23:12
【问题描述】:

我正在尝试创建一个 Teradata SQL 查询,该查询将返回每个用户的第 n 个按时间顺序访问的日期。例如,

user  |  visit_date
---------------------
  a      1/1      
  b      1/10
  c      1/20
  a      1/3
  a      1/4
  b      1/5
  c      1/15
  b      1/9


> magic_query_for_Second_visit;
user  |  second
------------------
  a       1/3
  b       1/9
  c       1/20

我尝试了类似下面的方法,但 Teradata 尖叫“WHERE 子句中不允许使用有序分析函数。”我已经拉了一段时间的头发,但没有取得太大进展。有人看过吗?

select user,
  row_number() over (partition by user order by visit_date desc) as rnum

from visitstable
  where rnum = 2

如果我排除 where,那么我的结果看起来很有希望......我只是无法提取我需要的东西!

 user |  visit_date | rnum
---------------------------
  a        1/1          1
  a        1/3          2
  a        1/4          3
  b        1/5          1
  b        1/9          2
  b        1/10         3 
  c        1/15         1
  c        1/20         2

提前感谢您的帮助!

【问题讨论】:

    标签: sql teradata


    【解决方案1】:
    SELECT 
        user
    
    FROM 
        visitstable
    
    QUALIFY ROW_NUMBER() OVER (
        PARTITION BY 
            user
        ORDER BY 
            visit_date DESC) = 2
    

    我从您的评论中看到,您不一定要依赖 Teradata 特定的 QUALIFY。以下是一种基于另一章回答的可移植解决方案(因为许多 RDBMS 现在都支持 CTE):

    WITH tmp (user, rnum) AS (
        SELECT 
            user, 
            ROW_NUMBER() OVER (
                PARTITION BY 
                    user 
                ORDER BY 
                    visit_date DESC) AS rnum 
        FROM 
            visitstable)
    SELECT
        tmp.*
    FROM 
        tmp
    WHERE 
        tmp.rnum = 2
    

    【讨论】:

    • 谢谢,亚当。 TD 不喜欢第一个解决方案。 QUALIFY BY ROW_NUMBER() 中的“BY”必须删除。第二个让我的大脑发出嘶嘶声,这在星期五早上很棒。谢谢!
    • 糟糕,很抱歉 BY 错字。我现在已经编辑了,谢谢。第二个示例是可用于主查询的临时表。一旦我掌握了语法,我发现只需将现有查询的第一步左右移动到WITH 子句中即可获得巨大的性能提升。祝你好运。
    【解决方案2】:

    哦,天哪,我应该查看文档。仅供参考,看起来qualify 允许您指定有序的分析约束。但是,qualify 不是 ANSI,所以我仍在为便携式解决方案分发积分...

    我能做到:

    select user,
      row_number() over (partition by user order by visit_date desc) as rnum
    
    from visitstable
    qualify rnum=2
    

    ...得到...

    user  |   visit_date  |  rnum
    -----------------------------
      a        1/3            2
      b        1/9            2
      c        1/20           2
    

    书签! :)

    【讨论】:

      【解决方案3】:

      您使用的是什么版本的 SQL?它看起来像 MS SQL Server 的更高版本,所以尝试使用像这样的“公用表表达式”...

      with cte as ( select user, row_number() over (partition by user order by visit_date desc) as rnum from visitstable )

      从 cte 中选择 * 其中 rnum = 2

      语法可能需要稍作调整,但这是一般原则。

      【讨论】:

      • 这是 Teradata... 我看看能否翻译您的建议。谢谢。
      • 如果您没有 where 子句,您的查询是否有效,并返回预期的行号?如果是这样,您可以将结果插入到临时表中,然后从中选择适当的行号。
      • 是的,临时表可能可以便携工作......我只是想尽量减少临时表的数量,因为有数亿条记录。
      猜你喜欢
      • 2019-05-06
      • 2015-03-16
      • 2012-07-13
      • 1970-01-01
      • 2014-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多