去除oracle時的一個問題解決歷程

問題模擬場景簡述:

首先,以前的oracle中有以下兩張表:user_info,city_info

user_info: user_id, register_time, register_city(整型)

city_info: id, name, pid

city_info採用的是樹形結構,根節點的pid爲0,樹的層級不確定,id從1開始,根節點爲各個省份和直轄市

user_info中的register_city對應的是city_info的id,並且沒有限制其必須是市,縣或是其他級別

現要隨時統計當前月份,各個省份和直轄市新註冊的用戶量,因爲oracle中有start with等相關操作,這個功能可以得到較好的實現,但pgsql裏,需要自己寫遞歸查詢,而且,輸入並不是外部傳入的一個變量或者定好的一個常量,而是另外一個表查詢出的結果集(因爲如果分開執行,查出所有user_info,再遍歷地去調遞歸sql,性能損失極大),實現相當困難且不會有很好的性能。


最終解決方案:

更改表結構,city_info擴增一個字段city_root,用於存放一個city所屬的省級city的id

寫一個遞歸sql一次性更改數據庫已有數據:

先查出所有省級city的id,遍歷調用遞歸sql,

將當前省級city下的所有city(包含省級自身)的city_root填充爲當前省級city的id:

<update id="changeOnce" parameterType="java.lang.Integer">
    update city_info t set t.city_root = #{Id}
    where t.id in
    (with RECURSIVE cte as
      (select t1.id, t1.pid from city_info t1 where t1.id = #{Id}
      union all
      select t2.id, t2.pid from conf_admin_city t2 inner join cte c on c.id = t2.pid
      ) select id from cte)
</update>

做完數據更改後,更改表的插入sql,使新插入的city記錄,city_root字段填爲父city的city_root


最後效果:性能非常好

因爲現在進行統計的過程只需要連表查詢就可以輕鬆搞定

<select id="getAddCount" resultMap="CountResult">
    select t1.city_root, count(1) as addCount
    from city_info t1, user_info t2
    where t2.register_city = t1.id
    and <![CDATA[t2.register_time < date_trunc( 'month', now())::timestamp + '1 month' ]]>
    and <![CDATA[t2.register_time >=  date_trunc( 'month', now())]]>
    group by t1.city_root
</select>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章