如何选择每组的前两行并在一列中计算它们之间的差异?

Posted

技术标签:

【中文标题】如何选择每组的前两行并在一列中计算它们之间的差异?【英文标题】:How to select the first two row of each group and count difference between them in one column? 【发布时间】:2016-11-03 19:36:57 【问题描述】:

我有这样的桌子

ID_WE   ID_B    ID_WO   RDATA   RSIZE
11111   22      1   1998-10-01  14
11111   22      2   1998-09-30  17
11111   23      1   1998-10-01  23
11112   22      1   1998-09-30  14

ID_WEID_BID_WO 一起是主键。对于每个组合 id-we, id_b 都很少有 ID_WO。每个ID_WO都有很多reads,reads信息在RDATARSIZE

我需要这样取表

ID_WE   ID_B    ID_WO   DAYS    DIF
11111   22      1       1       0

DIF 是给定ID_WO 的最后两次读取之间RSIZE 的差异, DAYS 是最后两次读取之间经过了多少天

它可能需要一些 group by 和 max(rdata) 来计算天数和大小的差异。我真的迷失了如何获得这样的结果。我将不胜感激如何获得所需结果的任何提示。

【问题讨论】:

ID_WE 和 ID_B 不能一起作为主键,因为有这样的重复。 哪个 Firebird 版本?使用 Firebird 3 可能比使用早期版本更容易。顺便说一句:鉴于示例数据,我不明白为什么 DAYS 的值是 780 而 DIF 的值是 6。 @Mark Rotteveel-Fierbird 2.1,你说得对,应该是 1 天 0 差异 @jarlh 我的错误应该是 ID_WE 和 ID_B 和 ID_WO 是主键 所以...对于给定的 ID_WE+ID_B,随着 ID_WO 增加,RDATA 日期减少?在您的数据中,11111-22-1 是在 1998 年 10 月 1 日读取的,但 11111-22-2 是在 1998 年 9 月 30 日读取的?对吗? 【参考方案1】:

试试这个

SELECT MIN(ID_WE) ID_WE,ID_B,ID_WO,DAYS,DIF
FROM
(
     SELECT MIN(ID_WE) ID_WE,MIN(ID_B) ID_B,MIN(ID_WO) ID_WO, 
            MAX(RDATA)-Min(RDATA) DAYS,MAX(RSIZE)-Min(RSIZE) DIF   
     FROM TABLE1
     GROUP BY ID_WE,ID_B
)AS G
GROUP BY ID_WE

【讨论】:

关闭,但 MAX(RDATA)-Min(RDATA)DAYS 给出了第一个和最后一个之间的区别,我需要最后两个。更像是 MAX(RDATA)-MAX2(RDATA)DAYS。其中 max2 是第二大的。 你能在 SQL Fiddle 中发布查询吗【参考方案2】:

代替 TABLE1,我构建了一些获取最后两个元素的东西:

SELECT MIN(ID_WE) ID_WE,ID_B,ID_WO,DAYS,DIF
FROM
 (
 SELECT MIN(d.ID_WE) ID_WE,MIN(d.ID_B) ID_B,MIN(d.ID_WO) ID_WO, 
        MAX(d.rdata)-Min(d.rdata) DAYS,MAX(d.RSIZE)-Min(d.RSIZE) DIF   
 FROM 
     (  select t.id_we, t.id_b, t.id_wo, t.max from 
       (( select b.id_we, b.id_b, b.id_wo, max(b.rdata) as max
            from test b
            where b.rdata NOT IN
                (select max(a.rdata)
                from test a
                group by a.id_we, a.id_b, a.id_wo
                )
            group by b.id_we, b.id_b, b.id_wo
        ) union
        (
          select e.id_we, e.id_b, e.id_wo, max(e.rdata)
          from test e
          group by e.id_we, e.id_b, e.id_wo
        )  
       ) t

        ) t4
        join test d on t4.id_we = d.id_we and d.id_b = t4.id_b and d.id_wo = t4.id_wo and d.rdata = t4.max
   GROUP BY t4.ID_WE,t4.ID_B
)AS G
GROUP BY ID_WE;

【讨论】:

【参考方案3】:

谢谢大家的cmets和答案,这让我走上了正确的思路。我终于想通了。在 Baron Schwartz 的博客上 this page 的帮助下(如果有人需要在 SQL 中选择每个组的第一/最少/最大行,这是有用的资源)。

我得到最大和第二大的RDATA 并添加到数据中对应的RSIZE 在这样的查询中,最大(FOO):

select oo.id_wej,oo.id_ob,oo.id_wo, oo.odata,oo.od
from (select id_wej,id_ob,id_wo,odata from odczyty
where odata = (select max(odata) from odczyty o where o.id_wej=odczyty.id_wej and o.id_ob=odczyty.id_ob and o.id_wo=odczyty.id_wo)) as x
inner join odczyty oo on oo.id_wej=x.id_wej and oo.id_ob=x.id_ob and oo.id_wo=x.id_wo and oo.odata=x.odata
order by id_wej,id_ob,id_wo)as ok
on od.id_wej=ok.id_wej and od.id_ob=ok.id_ob and od.id_wo=ok.id_wo

第二大(BAR):

select o.id_we,o.id_b,o.id_wo, o.rdata,o.rsize
from (select id_we,id_b,id_wo,rdata from odczyty
where rdata =(select max(rdata)
from odczyty o2
where o2.id_we=odczyty.id_we and o2.id_b=odczyty.id_b
and o2.id_wo=odczyty.id_wo and
rdata <(select max(rdata) from odczyty o3
where o3.id_we=o2.id_we and
o3.id_b=o2.id_b and o3.id_wo=o2.id_wo))) as x
inner join odczyty o on o.id_we=x.id_we and o.id_b=x.id_b and o.id_wo=x.id_wo and o.rdata=x.rdata

使用这两个查询我做了这个:

   select od.id_wej,od.id_ob,od.id_wo, ok.odata-od.odata as days,ok.od-od.od as dif
from(BAR)as od  inner join
(FOO)as ok
on od.id_wej=ok.id_wej and od.id_ob=ok.id_ob and od.id_wo=ok.id_wo
order by id_wej, id_ob, id_wo

为了便于阅读,我将插入的查询替换为 FOO 和 BAR。

【讨论】:

以上是关于如何选择每组的前两行并在一列中计算它们之间的差异?的主要内容,如果未能解决你的问题,请参考以下文章

检查每组的另一列中是不是存在列值

Pandas - 在两列中查找具有匹配值的行并在另一列中相乘

计算同一列之间的差异,在python中由另一列分组的连续行

PowerPivot:如何识别计算列中每组的最大值

如何获取同一列中两行之间的差异

如何在保持在另一列范围内的同时锻炼列中两个值之间的差异?