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最高のものを見つけたいと思っています. 構文的にも論理的にも正しい 2 つのサブクエリを使用していますが、間違っているように感じます。itp_sqitp_iditm_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);

より良い方法を使用したことはわかっていますが、その構文は私の心の蜘蛛の巣に溶け込んでいます

4

5 に答える 5

2

To get just one greatest itm_sq that's smaller than the one in your row:

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;

To break ties (multiple rows with the same itm_sq) you could ORDER BY additional columns.

This way you don't have to reuse anything. If you had to, a subquery or CTE would be the tools to use.


If you needed the previous itm_sq for every item sharing the same itp_id the window function lag() (or lead() with reversed order) would be instrumental:

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;
于 2013-04-14T01:26:26.660 に答える
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
于 2013-04-14T01:24:37.023 に答える
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必要に応じて

于 2013-04-14T01:24:06.680 に答える
0

よくわかりませんが、おそらく PostgreSQL のWITH Queries (Common Table Expressions)を使用できます。

于 2013-04-14T01:23:21.393 に答える
-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;
于 2013-04-14T01:14:52.823 に答える