記一次複雜的sql server xml欄位查詢

2021-08-25 21:30:51 字數 1961 閱讀 6706

專案中一直使用」no sql」的方式將entity序列化成xml格式儲存在sql server資料庫表的xml欄位中,最近終於要對資料進行遷移了,需要將資料遷移回關係型格式,因此也經歷了一次比較有趣而又複雜的xml查詢。

具體問題是這樣的。資料庫中有一張entitystate表用於儲存應用中所有被xml序列化的entity,表結構如下圖所示:

[img]

其中的xml欄位儲存了entity序列化之後的xml內容,tag欄位為entity的型別碼,是由entity型別經過雜湊之後計算出來的。

有乙個名為calendarmonth的entity,儲存了使用者乙個月每天的活動資訊。乙個具體的calendarmonth的xml欄位中可能儲存了如下的內容:

可以看到該calendarmonth 的xml欄位記錄了乙個使用者2023年6月份每一天的活動情況。

而新資料庫中以關係資料的方式按日為單位儲存使用者每天的活動情況,它的表結構如下圖所示:

[img]

新資料表字段與xml內容的對應關係是:

[table]

|firstactivities中的字段|entitystate中xml欄位中的內容|

|id|無對應,由新資料表在插入記錄時自動生成|

|userid|entity的userid屬性|

|date|由entity的year屬性確定年份,month屬性確定月份,其下每個dictionary的date屬性確定日期,最後拼成乙個日期字段|

|activity|對應到每個dictionary的activity屬性|

|timestamp|無對應內容,由新資料表在插入記錄時根據當前時間生成|

[/table]

我們要實現的任務是:根據對應關係,構造sql查詢將xml中的內容「適配」成新資料庫表firstactivities對應欄位中。這裡面有幾個難點:

[list]

[*]原表中的一條記錄(也就是一條xml欄位的內容)在新錶中變成了n條記錄。

[*]新錶中每一行的值既需要從xml中根節點entity中取,又需要從子節點dictionary中取得。

[/list]

下面分幾步來實現這個查詢sql。

[b]第一步: 從子節點中查詢每一天的日期(這裡單指日)和活動內容。[/b]

直接上sql:

再看(3)。這裡用到了nodes()方法,它的語法是:

nodes (xquery) as table(column)

結果是乙個包含原始 xml 例項的邏輯副本的行集。

我們這裡查詢xml內容中所有的/entity/list/dictionary節點,並放到表days的content欄位中。

最後看(1)。這裡使用了sql server xml資料型別的value()方法,該方法應用於 nodes() 所返回的行集,從原始 xml 例項中檢索多個值。它的語法是:

value (xquery, sqltype)

我們這裡使用了兩次value方法分別得到了日期和活動內容。

這一步的查詢結果如下圖所示。

[img]

[b]第二步:從xml根節點中查詢year,month和userid。[/b]

[img]

[b]第三步:組裝最後的結果。[/b]

現在已經離我們的適配最終結果很近了,只需要把年月日組裝成日期,再加上自動生成的id和timestamp就可以了。

(1)這裡我們使用了sql server的newid()方法自動生成uniqieidentifier欄位的值。

(2)這裡反覆使用了cast方法將年月日拼成了日期字段。

(3)這裡使用current_timestamp得到當前的timestamp值。

(4)將原來的查詢包含在乙個子查詢裡。

最終我們終於得到了如下結果:

[img]

大功告成!!

記一次複雜查詢

專案中有乙個需求,查出使用者取出,充值次數,金額,使用者名稱,金幣的總量和每局遊戲的盈虧等做乙個統計,而他們分布在個表中,分別是使用者表,使用者取出表,使用者充值表,每局遊戲表中。首先想到的就是要分組查詢,group by user.userid.因為有的使用者有充值記錄但不一定有取出記錄,所以需要...

記一次實驗 複雜函式指標的呼叫

下午突然發憤決定搞定複雜指標的相關問題,看了幾篇大大們的文章後,感覺略有收穫。個人的總結 從非保留字讀起,如果有多個非保留字 如函式指標中的形參名,雖然這並沒有必要 從最左邊的讀起。此後,如果遇到右括號,則向左讀。如果遇到左括號,則向右讀,讀完所有括號後再按優先順序分析一次。我們來試一試,我會說的詳...

記一次的使用

將jsp拆分frame框架,因為採用了第一種方式,一直在考慮用jquery非同步請求獲取資料,總是但不到效果,終於在js寫吐的時候選擇了第二種方式。參考網上的使用,大多是下面這個樣子,如果涉及靜態頁面之間定位,是沒有問題的 href 為目標頁面 通過target定位到frame views main...