Postgresql查询的奇怪行为

时间:2018-10-12 11:09:09

标签: postgresql postgresql-9.5 sql-view

我们在Postgres中创建了一个视图,但结果却很奇怪。

查看名称:event_puchase_product_overview

当我尝试使用*获取记录时,我得到了正确的结果。但是当我尝试获取特定字段时,会得到错误的值。

我希望这里附带的屏幕可以很好地解释问题。

select * 
from event_purchase_product_overview 
where id = 15065;

img

select id, departure_id 
from event_puchase_product_overview 
where id = 15065;

img

VIEW定义:

CREATE OR REPLACE VIEW public.event_puchase_product_overview AS 
 SELECT row_number() OVER () AS id,
    e.id AS departure_id,
    e.type AS event_type,
    e.name,
    p.id AS product_id,
    pc.name AS product_type,
    product_date.attribute AS option,
    p.upcomming_date AS supply_date,
    pr.date_end AS bid_deadline,
        CASE
            WHEN (pt.categ_id IN ( SELECT unnest(tt.category_ids) AS unnest
               FROM ( SELECT string_to_array(btrim(ir_config_parameter.value, '[]'::text), ', '::text)::integer[] AS category_ids
                       FROM ir_config_parameter
                      WHERE ir_config_parameter.key::text = 'trip_product_flight.product_category_hotel'::text) tt)) THEN e.maximum_rooms
            WHEN (pt.categ_id IN ( SELECT unnest(tt.category_ids) AS unnest
               FROM ( SELECT string_to_array(btrim(ir_config_parameter.value, '[]'::text), ', '::text)::integer[] AS category_ids
                       FROM ir_config_parameter
                      WHERE ir_config_parameter.key::text = 'trip_product_flight.product_category_flight'::text) tt)) THEN e.maximum_seats
            WHEN (pt.categ_id IN ( SELECT unnest(tt.category_ids) AS unnest
               FROM ( SELECT string_to_array(btrim(ir_config_parameter.value, '[]'::text), ', '::text)::integer[] AS category_ids
                       FROM ir_config_parameter
                      WHERE ir_config_parameter.key::text = 'trip_product_flight.product_category_bike'::text) tt)) THEN e.maximum_bikes
            ELSE e.maximum_seats
        END AS departure_qty,
        CASE
            WHEN now()::date > pr.date_end AND po.state::text = 'draft'::text THEN true
            ELSE false
        END AS is_deadline,
    pl.product_qty::integer AS purchased_qty,
    pl.comments,
    pl.price_unit AS unit_price,
    rp.id AS supplier,
    po.id AS po_ref,
    po.state AS po_state,
    po.date_order AS po_date,
    po.user_id AS operator,
    pl.po_state_line AS line_status
   FROM event_event e
     LEFT JOIN product_product p ON p.related_departure = e.id
     LEFT JOIN product_template pt ON pt.id = p.product_tmpl_id
     LEFT JOIN product_category pc ON pc.id = pt.categ_id
     LEFT JOIN purchase_order_line pl ON pl.product_id = p.id
     LEFT JOIN purchase_order po ON po.id = pl.order_id
     LEFT JOIN purchase_order_purchase_requisition_rel prr ON prr.purchase_order_id = po.id
     LEFT JOIN purchase_requisition pr ON pr.id = prr.purchase_requisition_id
     LEFT JOIN res_partner rp ON rp.id = po.partner_id
     LEFT JOIN ( SELECT p_1.id AS product_id,
            pav.name AS attribute
           FROM product_product p_1
             LEFT JOIN product_attribute_value_product_product_rel pa ON pa.prod_id = p_1.id
             LEFT JOIN product_attribute_value pav ON pav.id = pa.att_id
             LEFT JOIN product_attribute pat ON pat.id = pav.attribute_id
          WHERE pat.name::text <> ALL (ARRAY['Date'::character varying, 'Departure'::character varying]::text[])) product_date ON product_date.product_id = p.id
  WHERE (p.id IN ( SELECT DISTINCT mrp_bom_line.product_id
           FROM mrp_bom_line)) AND p.active
  ORDER BY e.id, pt.categ_id, p.id;

2 个答案:

答案 0 :(得分:0)

如果我添加新的event_event或新的product_product,我将在视图中获得row_number的新定义,则视图的列ID不稳定。

至少您不能将row_number用作视图的ID

如果您坚持使用row_number,则可以通过这种方式使用“创建日期”的“排序依据”,所有新记录都将作为视图中的最后一行,并且不会更改ID(row_number)与其他列之间的对应关系。

希望有帮助!

答案 1 :(得分:0)

查询的执行计划很可能取决于您选择的列。比较执行计划!

您的unspecified是使用id窗口函数生成的。现在,窗口函数是在row_number子句之前 执行的,因此顺序将取决于执行计划,并因此取决于您选择的列。

使用ORDER BY而不进行明确的排序没有任何意义。

要解决此问题,请不要使用

row_number

但是

row_number() OVER ()

这样您就可以进行可靠的订购。

此外,您应该在末尾省略row_number() OVER (ORDER BY e.id, pt.categ_id, p.id) 子句。