多个嵌套查询

Posted

技术标签:

【中文标题】多个嵌套查询【英文标题】:multiple nested queries 【发布时间】:2012-09-21 17:19:09 【问题描述】:

我目前正在尝试使用 mysql 和 openreports 优化报表以用于会计用途。虽然我确信有更好的工具来完成这项工作,但这些是我目前必须使用的。我正在做以下计算字段:

客户, 订单数量, 客户成本, 客户调整, 调整后的客户价格(客户成本 - 客户调整), 供应商成本, 供应商调整, 调整后的供应商价格(供应商成本 - 供应商调整), 保证金((客户开单 - 供应商开单)/客户开单), adj margin ((adj client price-adj vendor price)/adj client)

这些表非常大,我必须为每个内部连接加入 4 个表。之前的报告有一个联合,在联合的每一侧都有大约 20 个嵌套选择,它们都包含至少四个连接和计数。由于我正在根据先前的字段进行计算,因此每个嵌套选择会逐渐变大,其中包含所有嵌套选择、计数和来自先前计算的计算。该查询现在有 400 行,并且非常昂贵,并且对系统造成负担,尤其是在较大的客户端上。

我意识到有更好的工具来完成这项工作,但我想知道针对这种情况的理想解决方案是什么。我可以在查询中创建一个用户定义的变量并在以后使用它吗?如果我每个客户有多个查询,这会起作用吗?我不能在这篇文章中包含整个 400 行查询,但我可以提供任何有用的其他详细信息。任何见解将不胜感激。

select office_1.name as 'Client'
,count(distinct(property_1.id)) as 'Total Billed Orders',
(select format(coalesce(sum(serviceprice_2.amount),0),2)
    from cap.service_price serviceprice_2
    inner join cap.service service_2 on service_2.id = serviceprice_2.service_id
    inner join cap.service_area servicearea_2 on servicearea_2.id = service_2.service_area_id
    inner join cap.property property_2 on property_2.id = servicearea_2.property_id
    inner join cap.office office_2 on office_2.id = property_2.client_id
    where serviceprice_2.price_context = 'CLIENT'
    and serviceprice_2.price_type_id = 236
    && service_2.date_client_billed between '2012-09-01' and now()
    and service_2.gl_code_ap='4700-70-000'
    and service_2.date_cancelled is null
    and office_2.id = office_1.id) as 'Client Price'
/* other calculations between here */
from cap.service service_1
inner join cap.service_area servicearea_1 on servicearea_1.id = service_1.service_area_id
inner join cap.property property_1 on property_1.id = servicearea_1.property_id
inner join cap.office office_1 on office_1.id = property_1.client_id
inner join cap.office vendor_1 on vendor_1.id = service_1.vendor_id
where 
service_1.date_client_billed between '2012-09-01' and now()
and service_1.date_cancelled is null
and office_1.id = 26377 
and service_1.gl_code_ap='4700-70-000'
group by office_1.id
;

【问题讨论】:

【参考方案1】:

虽然对性能没有影响,但使用视图可以简化查询。

create view view1 as
select *
from 
    cap.service_price serviceprice_2
    inner join cap.service service_2 on service_2.id = serviceprice_2.service_id
    inner join cap.service_area servicearea_2 on servicearea_2.id = service_2.service_area_id
    inner join cap.property property_2 on property_2.id = servicearea_2.property_id
    inner join cap.office office_2 on office_2.id = property_2.client_id
;
create view view2 as
select *
from 
    cap.service service_1
    inner join cap.service_area servicearea_1 on servicearea_1.id = service_1.service_area_id
    inner join cap.property property_1 on property_1.id = servicearea_1.property_id
    inner join cap.office office_1 on office_1.id = property_1.client_id
    inner join cap.office vendor_1 on vendor_1.id = service_1.vendor_id

现在查询更易于管理:

select @client_price := format(coalesce(sum(serviceprice_2.amount),0),2)
from view1
where serviceprice_2.price_context = 'CLIENT'
    and serviceprice_2.price_type_id = 236
    && service_2.date_client_billed between '2012-09-01' and now()
    and service_2.gl_code_ap='4700-70-000'
    and service_2.date_cancelled is null
    and office_2.id = office_1.id
;
select 
    office_1.name as 'Client'
    ,count(distinct(property_1.id)) as 'Total Billed Orders',
    @client_price
/* other calculations between here */
from view2
where 
    service_1.date_client_billed between '2012-09-01' and now()
    and service_1.date_cancelled is null
    and office_1.id = 26377 
    and service_1.gl_code_ap='4700-70-000'
group by office_1.id

【讨论】:

我认为对性能的主要影响是我在整个脚本的许多子查询中加入了相同的表,但过滤器略有不同。此外,我一遍又一遍地执行相同的查询以继续进行计算,这就是为什么我想知道用户定义的变量在这种情况下是否有用,尽管我是新手并且没有看到使用它们的示例我描述的方式。不过,这一切都必须在一个独立的脚本中运行。做一个视图或添加一个表来存储这些值的月份间隔可能是答案 您的示例看起来更易于维护,因此我可能会对此进行研究。即使性能不会受到影响,它也可以帮助我保持理智。 @user1521319 是的,您可以将结果存储在变量中并稍后使用。我编辑了我的例子。 select @sum_service := 太棒了。如果我为多个客户端(多行)运行这些计算,这会混淆还是会跟踪每一行?我认为这对我的情况绝对有帮助。 @user1521319 现在我看到它在group by 内,它不会工作,因为它只会保留最后一个。删除它。

以上是关于多个嵌套查询的主要内容,如果未能解决你的问题,请参考以下文章

多个嵌套查询

如何使用 GraphQL Yoga 进行多个嵌套查询(GET 请求)?

具有多个嵌套解析器并将字段映射到参数的 GraphQL 查询

Mongoid查询嵌套embed文档通过属于和嵌入多个

在sql中对不相关嵌套查询的处理原则

优化多个嵌套选择的 SQL 查询