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_sq具有相同 itp_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

要获得比所在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;
于 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 回答