我的postgres查询有问题。查询花了太长时间,差不多27秒才得到结果,我不知道我需要做什么来解决
SELECT
sales.*,
customers.name AS customer_name,
customers.cpf_pf AS cpf,
customers.cnpj_pj AS cnpj,
customers.juridica AS tipo_pessoa,
status_sales.name AS status_name,
sales_status_histories.created_at AS data_modificacao,
sales_status_histories.obs as observacao,
users.name AS nome_vendedor
FROM sales
RIGHT JOIN customers ON sales.customer_id = customers.id
RIGHT JOIN sales_user_owners ON sales_user_owners.sale_id = sales.id
RIGHT JOIN sales_status_histories ON sales_status_histories.sale_id = sales.id
RIGHT JOIN status_sales ON status_sales.id = sales_status_histories.status_sale_id
RIGHT JOIN users ON users.id = sales_user_owners.user_id
WHERE sales_status_histories.id IN (SELECT id FROM ( SELECT *, row_number() over (PARTITION BY sale_id ORDER BY created_at DESC) AS rn FROM sales_status_histories) AS ssh WHERE rn=1 AND Date( (sales_status_histories.created_at at time zone 'UTC') at time zone 'America/Sao_Paulo') BETWEEN '2018-01-01 00:00:00' AND '2018-01-04 23:59:59')
AND sales_user_owners.id IN ( SELECT id FROM ( SELECT *, row_number() over (PARTITION BY sale_id ORDER BY created_at DESC) AS rn FROM sales_user_owners) AS so WHERE rn=1)
最大的问题在于:
WHERE sales_status_histories.id IN (SELECT id FROM ( SELECT *, row_number() over (PARTITION BY sale_id ORDER BY created_at DESC) AS rn FROM sales_status_histories) AS ssh WHERE rn=1 AND Date( (sales_status_histories.created_at at time zone 'UTC') at time zone 'America/Sao_Paulo') BETWEEN '2018-01-01 00:00:00' AND '2018-01-04 23:59:59')
此部分使用特定时间范围在sales_status_histories表中搜索销售的最后状态
销售可以在不同阶段具有倍数状态,但只有最后一个是当前状态,而最后一个对我来说在此查询中很重要,因为我需要获得在特定时间范围内更新的所有销售
有人可以帮我构建一个优化的查询,花费更少的时间来获得相同的结果吗?
我的应用程序是带有postgres的轨道上的红宝石
---编辑1 ----
有时我需要找到具有特定当前状态的销售。使用@bma建议我试过这样的事情:
(SELECT id, row_number() OVER (PARTITION BY sale_id ORDER BY created_at DESC) AS rn FROM sales_status_histories WHERE status_sale_id IN (2) AND DATE((sales_status_histories.created_at AT TIME ZONE 'UTC') AT TIME ZONE 'America/Sao_Paulo') BETWEEN '2018-01-01' AND '2018-01-04') AS ssh WHERE rn=1
正如您所看到的,我添加了status_sale_id IN(2),但在这种情况下,只返回某个时刻(并非总是当前状态)具有该特定状态的销售
答案 0 :(得分:0)
不是一个完整的答案,但是尝试的一件事可能是使用WITH子句使查询更具可读性,以便首先提取您感兴趣的sales_status_histories行,然后加入主SELECT。
注意:您可以使用SELECT DISTINCT sale_id FROM sales_status_histories ORDER BY created_at DESC仅获取具有最新更改的行而不是带有row_number()的子查询。我不知道这是否更有效,但阅读起来更简单。