来自表格
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_id
减少的最佳itm_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 :(得分:2)
要获得一个最大itm_sq
小于您行中的<{1}}:
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;
答案 1 :(得分: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
答案 2 :(得分:0)
我不确定,但也许你可以使用PostgreSQL的WITH Queries (Common Table Expressions)。
答案 3 :(得分: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
答案 4 :(得分:-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;