postgres中幾個復雜的sql語句
需求一
需要獲取一個問題列表,這個問題列表的排序方式是分為兩個部分,第一部分是一個已有的數組[0,579489,579482,579453,561983,561990,562083] 第二個部分是按照id進行排序,但是需要過濾掉前面已有的數組。
最開始的時候我大概是想這么寫的:
select * from question where id = any(
array_cat(
ARRAY[0,579489,579482,579453,561983,561990,562083]::integer[],
(select array(
select id from question where id not in
(0,579489,579482,579453,561983,561990,562083)
and status in (1, -1)
and created_at > 1426131436 order by id desc offset 0 limit 10 )
)::integer[]
)
)
這里用了個字查詢來查找問題,然后和array做一個鏈接。但是發現這個 = any 返回的結構並不是按照我想要的排序。有沒有辦法讓 = any 按照指定順序返回呢?后來經過別人幫忙,將sql語句改成:
select * from question q join (
select * from unnest(
array_cat( ARRAY[0,579489,579482,579453,561983,561990,562083]::integer[], (
select array(
select id from question where id not in (0,579489,579482,579453,561983,561990,562083) and status in (1, -1) and created_at > 1426131436 order by id desc offset 0 limit 10
)
)::integer[] )
) WITH ORDINALITY as ids(id, rn)
) as tmp on q.id = tmp.id order by tmp.rn
這里主要有幾個函數:
一個是unnest函數,是將一個array變成一個多行的子查詢結果。
一個是WITH ORDINALITY,這個函數是只在pg9.4中才增加的函數,和unnest一起使用能返回對應的數組和在數組中的排序。
需求二
現在有個表,有個字段是content,content 里面存儲的是雙層json,即
{"title": "testtest", "content": "{"id":23,"qid":580585,
"content":"\u8fd9\u4e2a\u662f\u8ffd\u95ee"}"}
現在我要獲取按照解析后的qid進行排序分頁的結構。
使用了json ->> 符號
語句實現如下:
select a.question_id, max(is_read) as is_read from (
select id, is_read, (content::json->>'content')::json->>'qid' as question_id
from inbox where receiver=1
) a group by a.question_id order by a.question_id desc offset 0 limit 10
這里的json->>直接使用了兩層解析結構。
總結
pgsql中的查詢函數非常神奇,只有你想不到的,沒有寫不了的。