在某些相关行中选择具有大于零的特定列的行

时间:2017-12-30 10:51:21

标签: sql postgresql postgresql-performance relational-division

我在Postgres 9.5数据库中有以下表格:

product_days

Column     | Type    | Modifiers
-----------+---------+----------------------------------------------
id         | integer | not null default nextval('product_days_id_seq'::regclass)
days_id    | integer |
product_id | integer |
available  | integer | 
price      | integer |
 Indexes:
"pk_product_days" PRIMARY KEY, btree (id)
"idx_product_days" btree (days_id)
"idx_product_days_0" btree (product_id)
Foreign-key constraints:
   "product_days_days_id_fkey" FOREIGN KEY (days_id) REFERENCES days(id)

product

 Column         |            Type             |                       Modifiers
----------------+-----------------------------+-----------------------------------------------------
id              | integer                     | not null default nextval('product_id_seq'::regclass)
name            | character varying(100)      |
number_of_items | integer                     |
created_at      | timestamp without time zone | default now()
updated_at      | timestamp without time zone | default now()
total_number    | integer                     |
 Indexes:
    "pk_product" PRIMARY KEY, btree (id)

product_days.product_id是指代product表的外键,available表示每天可用的产品数量。

我希望在特定日期(available > 0)获取所有可用的产品(days_id between 5 and 10)。它们应该在最近所有中提供。

目前我正在尝试使用以下查询获得结果,但我不确定它是否正确,或者这是最有效的方法:

select product.id as p_id, product.name as p_name, product.number_of_items as items
from product_days join product ON product_days.product_id = product.id
WHERE product_days.available > 0
AND  prodcut_days.days_id between 5 and 10
group by product.id
HAVING count(*) > 5;

输出应该是:

 p_id  | p_name    | items
-------+-----------+-------
 1     | product_1 | 4
 2     | product_2 | 13

我需要在SQL或plpgsql中运行此查询的最有效方法。

1 个答案:

答案 0 :(得分:3)

在澄清拼写错误后,是的,查询应该按照您的描述进行。

这相当于更快一点:

ALTER TABLE product_days ADD CONSTRAINT your_name_here UNIQUE (product_id, days_id);

每个产品和日期应该有UNIQUE constraint强制最多1个条目:

available

相关:

优化读取性能

如果您需要优化此特定查询的效果,并且有多个不合格的行(不是day_idCREATE INDEX idx_name_here ON product_days (product_id) WHERE available > 0 AND days_id BETWEEN 5 AND 10; 不匹配),最明智的武器将是{{3 }}:

autovacuum

如果SELECT id AS p_id, name AS p_name, number_of_items AS items FROM ( SELECT product_id AS id FROM product_days d5 JOIN product_days d6 USING (product_id) JOIN product_days d7 USING (product_id) JOIN product_days d8 USING (product_id) JOIN product_days d9 USING (product_id) JOIN product_days d10 USING (product_id) WHERE d5.days_id = 5 AND d5.available > 0 AND d6.days_id = 6 AND d6.available > 0 AND d7.days_id = 7 AND d7.available > 0 AND d8.days_id = 8 AND d8.available > 0 AND d9.days_id = 9 AND d9.available > 0 AND d10.days_id = 10 AND d10.available > 0 ) d JOIN product p USING (id); 正在运行并且表上的写入负载不是太大,则应该在此索引上看到仅索引扫描。

虽然使用了这个索引(或更通用的索引),但这个查询应该更快,但是:

unistall.tool

因为这是 partial index 的核心。参见: