2009-04-07 24 views
1

相關從第二表值我有以下兩個表在我的數據庫:查找而不訴諸PL/SQL

a)含在某一特定日期(你可能會覺得這些端口,比如獲取的值表,溫度讀數):

 
sensor_id |  acquired  | value 
----------+---------------------+-------- 
1   | 2009-04-01 10:00:00 | 20 
1   | 2009-04-01 10:01:00 | 21 
1   | 2009-04 01 10:02:00 | 20 
1   | 2009-04 01 10:09:00 | 20 
1   | 2009-04 01 10:11:00 | 25 
1   | 2009-04 01 10:15:00 | 30 
... 

讀數間隔可能不同,但組合(sensor_id,acquired)是唯一的。

b)含有時段和一個描述的第二個表(你可能認爲這些作爲,比方說,週期當有人接通的散熱器):

 
sensor_id |  start_date  |  end_date  | description 
----------+---------------------+---------------------+------------------ 
1   | 2009-04-01 10:00:00 | 2009-04-01 10:02:00 | some description 
1   | 2009-04-01 10:10:00 | 2009-04-01 10:14:00 | something else 

同樣,段的長度可能會有所不同,但將從來沒有任何給定傳感器重疊的時間段。

我想要得到的結果,看起來像這樣的任何傳感器和任何日期範圍:

 
sensor id |  start date  | v1 |  end date  | v2 | description 
----------+---------------------+----+---------------------+----+------------------ 
1   | 2009-04-01 10:00:00 | 20 | 2009-04-01 10:02:00 | 20 | some description 
1   | 2009-04-01 10:10:00 | 25 | 2009-04-01 10:14:00 | 30 | some description 

或文本從:給出一個sensor_id和日期範圍的range_startrange_end, 發現我所有的時間與日期範圍(即start_date < range_endend_date > range_start)重疊的週期以及這些行中的每一行,查找時間段爲start_dateend_date(查找第一行acquired > start_dateacquired > end_date)的值表中的對應值。

如果不是start_valueend_value列,這將成爲如何連接兩個表的教科書簡單示例。

我可以以某種方式在一個SQL語句中獲得所需的輸出,而不訴諸編寫PL/SQL函數來查找這些值嗎?

除非我忽略了一些明顯的東西,否則這不能用簡單的子選擇來完成。

數據庫是Oracle 11g,因此任何Oracle特定的功能都是可以接受的。

編輯:是的,循環是可能的,但我想知道這是否可以用一個SQL選擇完成。

回答

1

您可以試試這個。儘管如此,請注意最後的警告。

SELECT 
    RNG.sensor_id, 
    RNG.start_date, 
    RDG1.value AS v1, 
    RNG.end_date, 
    RDG2.value AS v2, 
    RNG.description 
FROM 
    Ranges RNG 
INNER JOIN Readings RDG1 ON 
    RDG1.sensor_id = RNG.sensor_id AND 
    RDG1.acquired => RNG.start_date 
LEFT OUTER JOIN Readings RDG1_NE ON 
    RDG1_NE.sensor_id = RDG1.sensor_id AND 
    RDG1_NE.acquired >= RNG.start_date AND 
    RDG1_NE.acquired < RDG1.acquired 
INNER JOIN Readings RDG2 ON 
    RDG2.sensor_id = RNG.sensor_id AND 
    RDG2.acquired => RNG.end_date 
LEFT OUTER JOIN Readings RDG1_NE ON 
    RDG2_NE.sensor_id = RDG2.sensor_id AND 
    RDG2_NE.acquired >= RNG.end_date AND 
    RDG2_NE.acquired < RDG2.acquired 
WHERE 
    RDG1_NE.sensor_id IS NULL AND 
    RDG2_NE.sensor_id IS NULL 

它使用一讀範圍的開始日期和結束日期(個人後第一次讀取之後,我會覺得使用的開始和結束前的最後日期會更有意義或最接近價值,但我不知道你的申請)。如果沒有這樣的閱讀,那麼你什麼也得不到。您可以將INNER JOINs更改爲OUTER,並根據自己的業務規則放入其他邏輯來處理這些情況。

0

它看起來很直截了當。

  1. 找到每個範圍的傳感器值。找到一行 - 我會打電話獲得這一行只是X - 其中X > start_dateacquired > start_dateacquired < X不存在任何其他行。結束日期也一樣。

  2. 在查詢提供的日期之後,只選擇滿足查詢的範圍 - start_date before和end_date。

在SQL中,這將是類似的東西。

SELECT R1.*, SV1.aquired, SV2.aquired 
FROM ranges R1 
INNER JOIN sensor_values SV1 ON SV1.sensor_id = R1.sensor_id 
INNER JOIN sensor_values SV2 ON SV2.sensor_id = R1.sensor_id 
WHERE SV1.aquired > R1.start_date 
AND NOT EXISTS (
    SELECT * 
    FROM sensor_values SV3 
    WHERE SV3.aquired > R1.start_date 
    AND SV3.aquired < SV1.aquired) 
AND SV2.aquired > R1.end_date 
AND NOT EXISTS (
    SELECT * 
    FROM sensor_values SV4 
    WHERE SV4.aquired > R1.end_date 
    AND SV4.aquired < SV2.aquired) 
AND R1.start_date < @range_start 
AND R1.end_date > @range_end 
+0

我的錯誤,我沒有澄清我試圖找到一種方法來在一個SQL查詢中執行此操作。否則,是的,你的想法是非常有效的,也是實現這一點最直接的方法。 – andri 2009-04-07 18:56:58

+0

我明白你只想要一個查詢。您可以將所有內容放在一個巨大的查詢中。不好,但可能。 – 2009-04-07 19:05:22

相關問題