2009-02-25 284 views
2

我有一个Informix数据库,其中包含很多不同位置的测量温度值。所有位置每15分钟进行一次测量,然后将时间戳加载到同一张表中。表看起来是这样的:SQL查找两行之间的差异

 
locId dtg    temp 
aaa  2009-02-25 10:00 15 
bbb  2009-02-25 10:00 20 
ccc  2009-02-25 10:00 24 
aaa  2009-02-25 09:45 13 
ccc  2009-02-25 09:45 16 
bbb  2009-02-25 09:45 18 
ddd  2009-02-25 09:45 12 
aaa  2009-02-25 09:30 11 
ccc  2009-02-25 09:30 14 
bbb  2009-02-25 09:30 15 
ddd  2009-02-25 09:30 10 

现在我想的是现在的我与所有站的最后两个测量之间的温度变化的查询。而且,只有那些具有更新测量结果的。例如在上面的表格中,位置ddd不会被包括在内。 所以结果就变成:

 
locId change 
aaa  2 
bbb  2 
ccc  8 

我有很多尝试,但我不能找到什么好的解决办法。实际上,它大约有700个地点是从网页上查询的,所以我认为查询需要相当高效。

会真的很感谢一些帮助!
//加斯帕

+0

为什么不包括ddd?它有一个入口在9:30,温度为10,另一个入口在9点45分,温度为12。 – jimmyorr 2009-02-25 23:15:59

+0

只有包含10:00和9:45数据的站点将被包括 – BCS 2009-02-26 01:19:58

回答

4
set now = select max(dtg) from table; 
set then = select max(dtg) from table where dtg < now; 

select locID, old.temp-new.temp from 
     table as old join 
     table as new 
     on old.locId = new.locID 
where 
     old.dtg = then and 
     new.dtg = now; 

假设所有的时间是准确的

+0

“所有时间都是准确的“我认为这段代码假设所有地点的最新两次读数将完全相同。似乎不太可能。也可能要编辑“Ware”到“Where” – JohnFx 2009-02-25 23:13:37

2

在伪SQL你可以做查询:

@now = Time Now 

Select Oldest.LocId, Oldest.timestamp, Oldest.temp - Newest.temp as Change 
(Select LocId, temp from Foo where timestamp < @now - 15 mins AND timestamp >= @now - 30 mins) Oldest 
    left join 
(Select LocId, temp from Foo where timestamp >= TimeNow - 15 mins) Newest 
    on Oldest.LocId = Newest.LocId 

如果将此定义为“好”的解决方案,但它应该工作,提供有两个数据点不知道每个位置。

1
declare @dt_latest datetime, @dt_prev datetime 

select @dt_latest = max(dtg) from Measures 
select @dt_prev = max(dtg) from Measures where dtg < @dt_latest 

select Latest.Locid, Latest.temp - Prev.temp 
from Measures as "Latest" 
inner join Measures as "Prev" on Latest.Locid = Prev.Locid 
where Latest.dtg = @dt_latest 
and Prev.dtg = @dt_prev 

编辑:同BCS基本上,打我吧!

0

给这样的尝试。它可能不是超级效率,但不像一些其他的答案,它将返回每个DIF LOCID

SELECT DISTINCT LocID, 
      (SELECT max(t3.temp)-min(t3.temp) from 
        (SELECT TOP 2 T2.temp 
        From Table2 T2 
        Where (t2.Locid=t1.locid) 
        order by DTG DESC) as t3 
      ) as Diff 
    FROM Table1 T1 

警告:我写这个使用T-SQL,但是试图坚持标准ANSI SQL尽可能为可移植性到Informix。

1

我不认为Informix具有像Oracle这样的分析功能,但如果这样做的话,这将是一个很好的使用它们的地方。以下是使用解析函数lag和max的Oracle示例。

安装脚本:

drop table temps; 
create table temps (
locId varchar2(3), 
dtg date, 
temp number(3) 
); 

insert into temps values ('aaa', to_date('2009-02-25 10:00','yyyy-mm-dd hh:mi'), 15); 
insert into temps values ('bbb', to_date('2009-02-25 10:00','yyyy-mm-dd hh:mi'), 20); 
insert into temps values ('ccc', to_date('2009-02-25 10:00','yyyy-mm-dd hh:mi'), 24); 
insert into temps values ('aaa', to_date('2009-02-25 09:45','yyyy-mm-dd hh:mi'), 13); 
insert into temps values ('ccc', to_date('2009-02-25 09:45','yyyy-mm-dd hh:mi'), 16); 
insert into temps values ('bbb', to_date('2009-02-25 09:45','yyyy-mm-dd hh:mi'), 18); 
insert into temps values ('ddd', to_date('2009-02-25 09:45','yyyy-mm-dd hh:mi'), 12); 
insert into temps values ('aaa', to_date('2009-02-25 09:30','yyyy-mm-dd hh:mi'), 11); 
insert into temps values ('ccc', to_date('2009-02-25 09:30','yyyy-mm-dd hh:mi'), 14); 
insert into temps values ('bbb', to_date('2009-02-25 09:30','yyyy-mm-dd hh:mi'), 15); 
insert into temps values ('ddd', to_date('2009-02-25 09:30','yyyy-mm-dd hh:mi'), 10); 
commit; 

Oracle特有的查询使用分析功能:

select locId, change 
    from (
select t.locId, 
     t.dtg, 
     t.temp, 
     -- difference between this records temperature and the record before it 
     t.temp - lag(t.temp) over (partition by t.locId order by t.dtg) change, 
     -- max date for this location 
     max(t.dtg) over (partition by t.locId) maxDtg, 
     max(t.dtg) over (partition by 1) overallMaxDtg 
    from temps t 
order by t.locId, t.dtg 
) where maxDtg = dtg -- only most recent measurement 
    and overallMaxDtg = maxDtg -- only stations with an 'updated measurement' 
    ; 

结果:

LOCID CHANGE 

aaa 2 
bbb 2 
ccc 8 

甲骨文分析良好的资源:http://www.psoug.org/reference/analytic_functions.html

4

感谢uglysmurf以SQL格式提供数据。

使用IDS(IBM Informix Dynamic Server)11.50版,可以使用以下查询。

CREATE TEMP TABLE temps 
(
    locId CHAR(3), 
    dtg  DATETIME YEAR TO MINUTE, 
    temp SMALLINT 
); 
INSERT INTO temps VALUES ('aaa', '2009-02-25 10:00', 15); 
INSERT INTO temps VALUES ('bbb', '2009-02-25 10:00', 20); 
INSERT INTO temps VALUES ('ccc', '2009-02-25 10:00', 24); 
INSERT INTO temps VALUES ('aaa', '2009-02-25 09:45', 13); 
INSERT INTO temps VALUES ('ccc', '2009-02-25 09:45', 16); 
INSERT INTO temps VALUES ('bbb', '2009-02-25 09:45', 18); 
INSERT INTO temps VALUES ('ddd', '2009-02-25 09:45', 12); 
INSERT INTO temps VALUES ('aaa', '2009-02-25 09:30', 11); 
INSERT INTO temps VALUES ('ccc', '2009-02-25 09:30', 14); 
INSERT INTO temps VALUES ('bbb', '2009-02-25 09:30', 15); 
INSERT INTO temps VALUES ('ddd', '2009-02-25 09:30', 10); 

SELECT latest.locID, latest.temp, prior.temp, 
     latest.temp - prior.temp as delta_temp, 
     latest.dtg, prior.dtg 
    FROM temps latest, temps prior 
    WHERE latest.locId = prior.locId 
     AND latest.dtg = prior.dtg + 15 UNITS MINUTE 
     AND latest.dtg = (SELECT MAX(dtg) FROM temps); 

结果(更多的列比请求,但您可以轻松修剪选择列表):

aaa 15 13 2 2009-02-25 10:00 2009-02-25 09:45 
ccc 24 16 8 2009-02-25 10:00 2009-02-25 09:45 
bbb 20 18 2 2009-02-25 10:00 2009-02-25 09:45 

请注意,此解决方案不依赖于电流(或NOW);它适用于最新的记录数据。 SELECT语句唯一与IDS相关的部分是'+ 15 UNITS MINUTE';也可以在Informix中编写为'+ INTERVAL(15) MINUTE TO MINUTE',在标准SQL中编写为'+ INTERVAL '15' MINUTE'(如果DBMS支持INTERVAL类型)。在表中使用DATETIME YEAR TO MINUTE是特定于Informix的;在这样的背景下,不要存储你不感兴趣的信息(如秒)。