我有一张有数百万行和数千辆汽车的汽车位置
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
问题是当输入新车位置时我需要检查已经创建的路线并将其添加到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
表格中创建一个插入触发器,每次插入搜索前一个车位并创建路线并插入route_sources
。但不是为每个插入做一个选择的粉丝,car_log的想法看起来太复杂了。有什么想法吗?
答案 0 :(得分:0)
http://rextester.com/NFTKN29525
不漂亮,但通常会创建一个CTE,您可以在其中查看每辆车的最后一个目的地,并将其与新车配对。在' B'的情况下,我们必须输入2条记录,查询的最后一个目的地没有更新,这就是为什么我必须让它从新数据中选择,如果可以的话。这种方法创建了一个记录,其中destination = origin,这就是我需要CTE的原因,我可以从中过滤出必要的内容。
为了遵守Stackoverflow规则,这里是查询本身:
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来控制这个决定。