我在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中运行此查询的最有效方法。
答案 0 :(得分:3)
在澄清拼写错误后,是的,查询应该按照您的描述进行。
这相当于更快一点:
ALTER TABLE product_days ADD CONSTRAINT your_name_here UNIQUE (product_id, days_id);
每个产品和日期应该有UNIQUE
constraint强制最多1个条目:
available
相关:
如果您需要优化此特定查询的效果,并且有多个不合格的行(不是day_id
或CREATE 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 的核心。参见: