2009-02-25 288 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的;在這樣的背景下,不要存儲你不感興趣的信息(如秒)。