Postgresql

避免多次加入同一個表

  • July 20, 2015

我有兩張桌子:

CREATE TABLE one (
 id int4 primary key,
 p_id int4,
 k_id int4,
 c_id int4
);

CREATE TABLE two(
id int4 primary key,
p_id int4,
k_id int4,
t_id int4,
pos int4
);

Table one: 是一個連接表,我在這個報告中使用它只是因為c_idand 來限制行數。

two:包含我的數據 a p_idk_id並且t_id可以有很多pos,所以我將它們分組並使用min(), 來獲取 min pos。我已經嘗試了一些方法來獲取我的所有數據,k_idp_id 是一種方法(使用這個解決方案我無法訂購pos),所以我最終這樣做了(見小提琴)

SELECT
 o.p_id,
 o.k_id,
 min(t.pos) as t_pos,
 min(t1.pos) as t1_pos
FROM one o
 LEFT JOIN two t ON t.p_id = o.p_id 
   AND t.k_id = o.k_id
   AND t.t_id = 1
 LEFT JOIN two t1 ON t1.p_id = o.p_id 
   AND t1.k_id = o.k_id
   AND t1.t_id = 2
WHERE o.p_id = 1 AND o.c_id = 1
GROUP BY 1, 2
LIMIT 1

此解決方案比另一篇文章中@Erwin Brandstetter 的解決方案慢 2-3 倍,但排序是可能的t_pos,並且還可以在例如t1_pos哪裡獲取所有數據。type_id = 1``pos = 1

有沒有更好的方法來實現相同的輸出並提高速度並能夠對我的數據(t_post1_pos列)進行排序?

試試這對你有多好

將兩個 t_id 的表二的左連接轉換為一個內連接。在計算最小值時,使用 case 語句根據值 t_id 拆分為兩列。我們在這裡保存的是兩次掃描表和與左連接相比的內連接

SELECT
   o.p_id,
   o.k_id,
   MIN(case when t.t_id = 1 then t.pos else null end) AS t_pos,
   MIN(case when t.t_id = 2 then t.pos else null end) AS t1_pos
FROM
   one o
INNER JOIN two T ON t.p_id = o.p_id
AND t.k_id = o.k_id
AND t.t_id =any ( 1,2)
WHERE
   o.p_id = 1
AND o.c_id = 1
GROUP BY
   1,
   2
LIMIT 1

引用自:https://dba.stackexchange.com/questions/107316