查找最新和最近一期的差异

时间:2015-08-01 11:20:00

标签: mysql sql

表的结构类似于

insert into events values
(2,   5,  '2015-05-09 12:42:00'),
(4, -42,  '2015-05-09 13:19:57'),
(2,   2,  '2015-05-09 14:48:39'),
(2,   7,  '2015-05-09 13:54:39'),
(3,  16,  '2015-05-09 13:19:57'),
(3,  20,  '2015-05-09 15:01:09') 

插入了一些值,例如

event_type value
2          -5
3           4

我想写一个查询,对于已经多次注册的每个event_type,返回最新值和第二个最新值之间的差值。

鉴于以上数据,输出应该像

select event_type,value,time from events group by event_type order by event_type desc;

select * from events group by event_type order by event_type ;

我可以使用以下查询显示最低和最高。这是我可以达到的距离..在进一步的方式上融合。

import javax.swing.JOptionPane;

public class WhileEx {

public static void main(String[] args){ 

int start = Integer.parseInt(JOptionPane.showInputDialog("Enter a starting number (integer)")); 
int end = Integer.parseInt(JOptionPane.showInputDialog("Enter an ending number (integer)"));        

while (start < end)
{
    start = start * 4;
    System.out.print (start +  "  ");       
}
}
}

13 个答案:

答案 0 :(得分:7)

我没有看到与MySQL或PostgreSQL相关的答案。所以,这是我的方法,以及MySQL / PostgreSQL的工作解决方案:

resources

答案 1 :(得分:6)

我从Shadkhan修改/简化了解决方案。适用于MySQL,Sqlite,PostgreSQL

fiddle

SELECT e1.event_type, (e1.value - e2.value) AS value FROM
events e1
JOIN
events e2
ON
e1.event_type = e2.event_type
AND
e1.time = (SELECT time FROM events temp1 WHERE
           temp1.event_type=e1.event_type ORDER BY time DESC LIMIT 1)
AND
e2.time = (SELECT time FROM events temp2 WHERE
           temp2.event_type=e2.event_type ORDER BY time DESC LIMIT 1 OFFSET 1)

答案 2 :(得分:3)

当作者问我如何在SQL Server或Oracle中执行此操作时,这里的解决方案应该适用于它们(不是在MYSQL中):

with cte1 as (
    select e.event_type,
        value - lead(value,1) over (partition by e.event_type order by time desc) value,
        row_number() over (partition by e.event_type order by time desc) xrow
    from t_events e
)
select event_type, value from cte1
where xrow = 1 and value is not null

这是小提琴: http://www.sqlfiddle.com/#!4/9271a/19

我所做的是使用聚合函数按日期排序行(使用row_number函数)并计算当前行和下一行之间的差异(使用lead函数)。准备好之后,我只需要删除不再需要的行。

我不得不更改创建并为Oracle插入一点(并且可能需要对SQL Server进行另一次调整),但select语句应该适用于它们。

答案 3 :(得分:2)

首先我尝试使用两个以上的记录来获取每个event_type

(SELECT  e.event_type 
 from events e 
 group by e.event_type
 having count(e.event_type)>=2 
) g --get more than equals two records
之后

获取每个event_type中的第一条记录

(select r.event_type, r.value
 from   (SELECT   ROW_NUMBER() OVER (PARTITION BY e.event_type ORDER BY time Desc) AS Group_id,e.*
         from  g left join events e on g.event_type= e.event_type 
         order by e.event_type
        )r 
 where r.Group_id =1 -- get first row of group
)row1

之后在每个event_type中获取第二条记录

(select r.event_type, r.value
 from   (SELECT   ROW_NUMBER() OVER (PARTITION BY e.event_type ORDER BY time Desc) AS Group_id,e.*
         from  g left join events e on g.event_type= e.event_type 
         order by e.event_type
        )r 
 where r.Group_id =2 -- get second row of group
)row2

最后加入最后两个查询来计算答案

select row1.event_type , row1.value -row2.value
from  row1 join  row2 on row1.event_type= row2.event_type
  

最后的答案是:

 select row1.event_type , row1.value -row2.value
    from    (select r.event_type, r.value
             from   (SELECT   ROW_NUMBER() OVER (PARTITION BY e.event_type ORDER BY time Desc) AS Group_id,e.*
                    from (SELECT  e.event_type 
                          from events e 
                          group by e.event_type
                          having count(e.event_type)>=2 
                          ) g --get more than equals two records
                          left join events e on g.event_type= e.event_type 
                          order by e.event_type
                    )r 
             where r.Group_id =1
            )row1--get first records in each groups
       join 
            (select r.event_type, r.value
             from   (SELECT   ROW_NUMBER() OVER (PARTITION BY e.event_type ORDER BY time Desc) AS Group_id,e.*
                    from (SELECT  e.event_type 
                          from events e 
                          group by e.event_type
                          having count(e.event_type)>=2 
                          ) g --get more than equals two records
                          left join events e on g.event_type= e.event_type 
                          order by e.event_type
                    )r 
             where r.Group_id =2
            )row2--get Second records in each groups
        on row1.event_type= row2.event_type

答案 4 :(得分:2)

这是我的查询,

SELECT a.event_type as event_type,
       a.value-b.value as diff_value
FROM
  (SELECT e1.*
   FROM EVENTS e1,
     (SELECT event_type,
             max(TIME) AS TIME
      FROM EVENTS
      GROUP BY event_type
      HAVING count(event_type) > 1) MAX
   WHERE e1.event_type = max.event_type
     AND e1.time = max.time) a,

  ( SELECT e1.*
   FROM EVENTS e1,

     (SELECT e1.event_type,
             max(e1.time) AS TIME
      FROM EVENTS e1,
        (SELECT event_type,
                max(TIME) AS TIME
         FROM EVENTS
         GROUP BY event_type
         HAVING count(event_type) > 1) MAX
      WHERE e1.event_type = max.event_type
        AND e1.time < max.time
      GROUP BY e1.event_type) max2
   WHERE e1.event_type = max2.event_type
     AND e1.time = max2.time ) b
WHERE a.event_type = b.event_type

旁注: a是最大值, b是第二最大值
使用https://sqliteonline.com/创建表并派生上述查询。

答案 5 :(得分:1)

<强>计划

  
      
  1. 使用滞后变量来计算相同事​​件类型的值差异(使用良好的顺序)
  2.   
  3. 过滤值,其中值差异为非空
  4.   

<强>查询

set @rnk  := 0;

set @lag_ev := null;
set @lag_va := null;

select lagged.event_type, lagged.diff_val as value_difference
from
(
  select ev.*,
  case when @lag_ev is not null and @lag_ev = event_type
       then @rnk := @rnk + 1
       else @rnk := 0
  end as rnk,

  case when @rnk = 1
       then @lag_va - value
       else null
  end as diff_val,
  @lag_ev := event_type as lag_ev,
  @lag_va := value as lag_va
  from events ev
  order by event_type, time desc
) lagged
where lagged.diff_val is not null
order by lagged.value
;

<强>输出

+------------+----------+
| event_type | diff_val |
+------------+----------+
|          2 |       -5 |
|          3 |        4 |
+------------+----------+

sqlfiddle

答案 6 :(得分:0)

试试这个,

;WITH CTE
     AS (SELECT event_type,
                value,
                time,
                Row_number()
                  OVER(
                    PARTITION BY event_type
                    ORDER BY event_type) AS RN
         FROM   #t_events)
SELECT A.event_type,
       ( A.value - B.value ) AS Value
FROM   (SELECT *
        FROM   CTE
        WHERE  RN = 1)A
JOIN   (SELECT *
        FROM   CTE
        WHERE  RN = 2)B ON A.event_type = B.event_TYPE 

答案 7 :(得分:0)

几天前,在一次采访中得到了同样的问题。这是我的答案,不使用任何子查询。

<application>
<receiver android:name="my_receiver" />
</application>
<permission android:name="name"
          android:label="my_permission"
          android:protectionLevel="signature">
<uses-permission android:name="name"/>

答案 8 :(得分:0)

对于MySQL

SELECT ee.event_type,(ee.value - e1.value) AS VALUE 
FROM (
    SELECT * FROM `events` e GROUP BY e.event_type HAVING COUNT(e.event_type) > 1) AS t
    JOIN `events` ee ON ee.event_type = t.event_type 
    AND ee.time = (SELECT MAX(eee.time) 
    FROM  `events` eee WHERE eee.event_type = ee.event_type ORDER BY eee.time DESC LIMIT 1)
    JOIN `events` e1 ON e1.event_type = t.event_type 
    AND e1.time = (SELECT e2.time 
    FROM `events` e2 WHERE e2.event_type = e1.event_type ORDER BY e2.time DESC  LIMIT 1,1);

答案 9 :(得分:0)

我会这样做:D

WITH CTE AS
 (
SELECT     event_type
           ,val
           ,timee
           ,ROW_NUMBER() OVER ( PARTITION BY event_type ORDER BY Timee DESC) AS  Stamp


FROM        eventss2
--ORDER BY  price

)

SELECT      event_type
       ,SUM (CASE WHEN Stamp=1 THEN val ELSE  val*-1 END ) AS 'pricedif'
FROM        CTE

WHERE       Stamp<=2
GROUP BY    event_type
HAVING      SUM(stamp)>1

答案 10 :(得分:0)

我从 SQLite 提出了这样的解决方案。

drop table if exists events;

create table events(event_type integer not null, 
value integer not null, time timestamp not null, 
    unique(event_type, time));

insert into events
values(2, 5, '2015-05-09 12:42:00'), (4, -42, '2015-05-09 13:19:57'), 
(2, 2, '2015-05-09 14:48:39'), (2, 7, '2015-05-09 13:54:39'), 
(3, 16, '2015-05-09 13:19:57'), (3, 20, '2015-05-09 15:01:09');
select event_type,
sum(
    case num when 1 then 1 when 2 then - 1
    else 0 end * value) value
from(select row_number() over(partition by event_type order by time desc) num, * 
from events)
group by event_type
having count() > 1

答案 11 :(得分:0)

使用公用表表达式:

WITH evt AS
(
  select
    event_type,
    value,
    rank() over(partition by event_type order by time desc) rnk
  from events
)
select
    t1.event_type, t1.value - t2.value
from evt t1, evt t2
where t1.event_type = t2.event_type
and t1.rnk = 1
and t2.rnk = 2

没有任何 CTE

select t1.event_type, t1.value - t2.value from
(
select
    event_type,
    value,
    rank() over(partition by event_type order by time desc) rnk
from events
)t1,
(
select
    event_type,
    value,
    rank() over(partition by event_type order by time desc) rnk
from events
)t2
where t1.event_type = t2.event_type
and t1.rnk = 1
and t2.rnk = 2
;

答案 12 :(得分:-1)

with CteEvt
as
(
SELECT
event_type,
value,
time,
dense_rank() over (partition by event_type order by time desc) as rnk
from events
order by event_type 
)

select c1.event_type,
(c1.value- (case when c2.value is null then 0 else c2.value end)) as value
 from CteEvt c1
 inner join CteEvt c2 on c1.event_type=c2.event_type and c2.rnk=2
 where c1.rnk=1