【问题标题】:iterating through an sql table efficiently高效地遍历 sql 表
【发布时间】:2012-08-21 21:46:29
【问题描述】:

我有一个包含 3 列 rcvr_id(user id)、mth_id 和 tpv 的表。 mth_id 计算为 (2012-1900)*12+1,2,3(取决于是 jan,feb,march)。例如,2011 年 12 月的 mth_id 是 1344,2012 年 1 月是 1345。第三列是 tpv,它是一个十进制数,用于保存该月用户的交易。一个示例表是

rcvr_id           mth_id           tpv
                    .
                    .
                    .
1                 1326             23
1                 1327             13
1                 1329             9 
1                 1345             2
1                 1330             25
1                 1350             22
2                 1325             31
2                 1351             23    
3                 1327             130
3                 1329             90 
3                 1345             20
3                 1330             250
3                 1350             220  
                    .
                    .
                    .

对于其他用户以此类推(mth_ids 可能不排序)(rcvr_id 和 mth_id 一起构成主键)。必须忽略 Rcvr 2,因为他在 1326 和 1350 之间没有 tpv。

mth_id 中缺少的行值表示该月 rcvr 的 tpv 为 0。 即 1328,1331 到 1344,1346 到 1350 tpv 为 0。

问题:我想创建一个包含两列 rcvr_id、mth_id 和第三列 -change_in_tpv 的表。例如,对于 1327 月份 .. 行将类似于

1        1327       10,i.e (tpv of 1327-tpv of 1326)

对于用户 1对于 1347 月,更改 tpv=1347 月的 tpv- 1346 月的 tpv(即使两行都不存在,我必须将它们的 tpv 设为 0)。对于 1346,tpv 将 = 1346 的 tpv-1345 的 tpv=-2。

对于每个接收器(tpv 介于 1326 和 1350 之间),我需要计算 1327 到 1350 个月的 tpv 变化。

详细信息:Teradata,超过百万行。我如何做到并高效地做到这一点。

可以使用多个查询/临时表

【问题讨论】:

  • 抱歉这么多编辑:X
  • 您已将其标记为 Oracle,但您在描述中说它是 Teradata(并且它也被标记为 Teradata)。 Oracle 参与了这个过程的哪些环节?
  • 哦,是的,对不起。不习惯

标签: sql loops teradata


【解决方案1】:

您可以通过简单的自联接来完成大部分操作:

select t.rcvr_id, t.mth_id, (t.tpv - coalesce(tprev.tpv, 0) as diff
from t left outer join
     t tprev
     on t.rcvr_id = tprev.rcvr_id and
        t.mth_id = tprev.mth_id+1

要获得所有月份,需要有一张驾驶台。让我假设您有一张包含月份的表格,我将其称为月份:

select tm.rcvr_id, tm.mth_id, (coalesce(t.tpv, 0) - coalesce(tprev.tpv, 0) as diff
from (select distinct t.rcvr_id, m.mth_id
      from t cross join
           months m
     ) tm left outer join
     t
     on tm.rcvr_id = t.rcvr_id and
        tm.mth_id = t.mth_id left outer join
     t tprev
     on t.rcvr_id = tprev.rcvr_id and
        t.mth_id = tprev.mth_id+1

如果您没有月份参考表,您可以动态创建月份列表(假设每个月至少在原始表中出现一次):

select tm.rcvr_id, tm.mth_id, (coalesce(t.tpv, 0) - coalesce(tprev.tpv, 0) as diff
from (select r.rcvr_id, m.mth_id
      from (select distinct t.rcvr_id from t) r cross join
           (select distinct t.mth_id from t) m
     ) tm left outer join
     t
     on tm.rcvr_id = t.rcvr_id and
        tm.mth_id = t.mth_id left outer join
     t tprev
     on t.rcvr_id = tprev.rcvr_id and
        t.mth_id = tprev.mth_id+1

【讨论】:

  • 你希望我创建一个只有一列且值介于 1326 和 1350 之间的月份表 m 吗?我必须使用您编写的两个代码吗?
  • @ganducoder 。 . .尝试查询的第一个版本。它为原始表中的每一行返回一行。听起来您还想通过包括不在表格中的月份来“填充”输出。如果是这样,您需要一种方法来获得这些月份。这就是第二个查询所暗示的。顺便说一句,我很惊讶如果你有一个名为 mth_id 的列,你却没有它的参考表。
  • 参考表不是问题,我可以单独创建。假设我制作了一张表,其中一列 mth_id 的值从 1326 到 1350。然后我运行你的两个代码。对吗?
猜你喜欢
  • 1970-01-01
  • 2022-01-23
  • 2015-07-25
  • 1970-01-01
  • 2019-11-05
  • 1970-01-01
  • 1970-01-01
  • 2017-05-31
  • 1970-01-01
相关资源
最近更新 更多