2013-04-14 73 views
2

從表,查詢語法最好使用子查詢不止一次

create table seeplai.item(
    itm_id serial primary key, 
    itp_id int  not null references seeplai.item_type, 
    itm_sq int2 not null default 10, 
    ...) 
create index item_itp_sq on seeplai.item(itp_id, itm_sq); 

使用的item記錄爲基礎,我希望能夠找到具有相同itp_id,並且具有itm_sq少最大itp_sq。現在使用兩個子查詢,這在語法上和邏輯上都是正確的,但感覺不對。

select max(itm_sq) 
into v_prev_sq 
from seeplai.item itm 
where itm.itp_id = (select itp_id from seeplai.item where itm_id=p_itm_id) 
and  itm.itm_sq < (select itm_sq from seeplai.item where itm_id=p_itm_id); 

知道我使用了一個較好的方法,但它的語法已經溶入我的腦海裏的蜘蛛網

+0

'itm_tp'是不是在你的定義? –

+0

'itm_tp' =>'itp_id' - 固定 –

回答

2

得到的只是一個最大itm_sq比一個你的行中較小:

SELECT i2.itm_sq 
FROM seeplai.item i 
JOIN seeplai.item i2 USING (itp_id) 
WHERE i.itm_id = p_itm_id 
AND  i2.itm_sq < i.itm_sq 
ORDER BY i2.itm_sq DESC 
LIMIT 1; 

打破平局(具有相同的itm_sq多行)你可以ORDER BY附加列。

這樣你就不必再使用任何東西。如果你不得不,子查詢或CTE將是使用的工具。


如果您需要以前itm_sq項目共享相同itp_id窗函數lag()(或lead()有相反的順序)將儀器:

SELECT i2.*, lag(i2.itm_sq) OVER (ORDER BY i2.itm_sq) AS previous_itm_sq 
FROM seeplai.item i 
JOIN seeplai.item i2 USING (itp_id) 
WHERE i.itm_id = p_itm_id 
ORDER BY i2.itm_sq DESC; 
+0

它只是8:30,你迫使我進入我的第二杯咖啡 –

+0

@ccyoung:你有什麼得到速度。 ;) –

+0

好的,這是非常酷,像往常一樣。再次我的欽佩。也感謝不要在今天把CTE強加給我。 –

-1

剛子查詢的值存儲在一個變量:

declare @retVal varchar(20); 
set @retVal = select itm_tp from seeplai.item where itm_id=p_itm_id 

select max(itm_sq) 
into v_prev_sq 
from seeplai.item itm 
where itm.itm_tp = @retVal 
and  itm.itm_sq < @retVal; 
+0

一個可能,是肯定的。但實際上,在單個SQL語句中這樣做很不錯 - 不幸的是 - 現在完全逃脫了我。 –

+0

這是無效的Postgres語法。看起來像t-SQL? –

0

也許你正在尋找公用表表達式? http://www.postgresql.org/docs/9.2/static/queries-with.html

雖然我認爲這是比較容易使用實際上加入做...

select max(itm_0.itm_sq) 
into v_prev_sq 
from seeplai.item itm_0, 
join itm_1 
on itm_0.itm_tp = itm_1.itm_tp 
and itm_0.itm_sq < itm_1.itm_sq 
and itm_0.itm_id = itm_1.p_itm_id 
group by itm_1.p_itm_id 

可能使用DISTINCT ON如果需要

+0

你爲什麼使用'group by'? –

+0

@ccyoung:你在查詢中使用了一個最大值,所以我認爲會有超過1行。如果不是的話,你可以通過離開小組。 – Wolph

+0

你是對的 - 好點 –

1

你需要加入表本身:

select max(itm_sq) 
into v_prev_sq 
from seeplai.item itm 
join seeplai.item itm2 on itm.itm_tp = itm2.itm_tp and itm2.itm_id=p_itm_id 
join seeplai.item itm3 on itm.itm_sq < itm3.itm_sq and itm3.itm_id=p_itm_id 

這是您的查詢的「直接翻譯」,但我認爲這種簡化也將工作:

select max(itm_sq) 
into v_prev_sq 
from seeplai.item itm 
join seeplai.item itm2 
    on itm.itm_tp = itm2.itm_tp 
    and itm2.itm_id = p_itm_id 
    and itm.itm_sq < itm2.itm_sq 
+0

你的第二個版本對我來說很有意義。 –