2017-06-22 82 views
0

我的車位置的表數百萬行和cars_id如何合併新的記錄,而不計算所有的記錄再次

SQL DEMO

ID Car_ID .... other fields 
1 A 
2 B 
3 B 
4 A 
5 A 

我需要爲每個汽車路線萬。因此,與此查詢:

WITH cte as (
    SELECT ID, CAR_ID, 
      ROW_NUMBER() OVER (PARTITION BY CAR_ID ORDER BY ID) as rn 
    FROM myTable 
) 
SELECT o.CAR_ID, o.ID, d.ID 
FROM cte as o  -- origin 
LEFT JOIN cte as d -- destination 
    ON o.rn = d.rn - 1 
AND o."Car_ID" = d."Car_ID" 
WHERE d.ID IS NOT NULL 

我插在route_sources

ROUTE_SOURCE_id CAR_ID ORIGIN_ID DESTINATION_ID 
     1    A   1    4 
     2    B   2    3 
     3    A   4    5 

路由問題是,當進入新的汽車位置,我需要檢查什麼路線的arent已經創建並把它添加到route_sources表。

有關示例新行

ID Car_ID 
6 A 
7 B 
8 B 

然後,我只需要添加以下路線:

ROUTE_SOURCE_id CAR_ID ORIGIN_ID DESTINATION_ID 
     4    A   5    6 
     5    B   3    7 
     6    B   7    8 

我知道該怎麼做合併,注意版本是9.4所以INSERT ... ON CONFLICT UPDATE (and ON CONFLICT DO NOTHING), i.e. upsert.不可用。

但我的問題是我不想每次計算數百萬的路線只是爲了添加新的路線。

考慮car_position表可以獲得6000分鐘的新記錄。

我覺得有兩個選項:

  • car_positions表創建一個INSERT觸發器,並與每個插入搜索以前的轎廂位置和創建路由和插入route_sources
  • 創建一個car_log表,我保存用於爲每輛車創建路線的最後一個ID,然後創建路線過程將檢查比這些ID更新的ID。

但不是爲每個插入做一個select,並且car_log想法看起來太複雜了。有任何想法嗎?

+0

你的'Id'看起來像一個系列。如果你使用它作爲位置的標識符,如果b> a – joop

+0

@joop yes,id是連續的,則對象(汽車)永遠不會從loc_b返回* loc_a。還有其他字段表示'(x,y)'。但是當添加id_c需要添加id_b-> id_c'時,路由爲'id_a - > id_b'。 –

回答

0

http://rextester.com/NFTKN29525

不漂亮,但通常產生CTE,你看每節車廂的最後一個目的地,並用新的配對。在'B'的情況下,我們必須輸入2條記錄,查詢中的最後一個目的地沒有更新,這就是爲什麼我必須讓它從新數據中進行選擇(如果可以的話)。這種方法創建了一個記錄,其中destination = origin,這就是爲什麼我需要CTE,我可以稍後從中篩選出必要的內容。

爲了通過#1遵守規則,這裏是查詢本身:

WITH new_routes AS (
    SELECT DISTINCT 
     n."Car_ID", 
     greatest(first_value(r.destination_id) OVER (PARTITION BY r."Car_ID" ORDER BY r.destination_id DESC), 
       lag(n.destination_id, 1) OVER (PARTITION BY n."Car_ID" ORDER BY n.destination_id)) AS origin_id, 
     n.destination_id 
    FROM newData n 
    JOIN result r ON r."Car_ID" = n."Car_ID" AND r.destination_id<n.destination_id 
) 
INSERT INTO result ("Car_ID", origin_id, destination_id) 
SELECT * FROM new_routes WHERE origin_id<>destination_id 
ORDER BY destination_id; 

假設result是你以前的工作表,newData是剛進來的新數據。

如果你有一輛新車C,你可以使用你以前的方法爲它創建路線。使用plpgsql來控制這個決定。

+0

唯一的問題是「新數據」被插入到同一張表上。所以沒有辦法知道哪一個是新的行。我需要跟蹤流程最後一次運行的時間,但似乎是一個很好的解決方案。 –