【问题标题】:Select with multiple subselects on same table with parent-children like relations在具有父子关系的同一张表上使用多个子选择进行选择
【发布时间】:2020-01-31 14:18:27
【问题描述】:

我有一个包含机器数据的表。其中包括(唯一)设备编号 (EMEQP#)、财务成本 (EMCOST)、当前值 (EMBOOK) 和设备链接 (EMLEQP) 列。一些机器由其他几台机器组成,这些机器通过将“父”机器的 EMQP# 放在 EMLEQP 列中来链接。有时会填充父级的 EMLEQP(使用其自己的 EMEQP#),但也可以为空。也不是每个父母都有孩子,但即使这样,EMLEQP 也可以填写或不填写。

这是数据的简化示例:

EMEQP#    |  EMLEQP  |  EMCOST  |  EMBOOK  
ACMD001   |  ACMD001 |  10      |  12  
ACMD001A  |  ACMD001 |  8       |  1  
ACMD002   |  NULL    |  10      |  12  
SLE003    |  NULL    |  11      |  5
RUP5120   |  SLE003  |  12      |  7  

所以在这种情况下,ACMD001、ACMD002 和 SLE003 是父机器(因为 EMLEQP 为空或与 EMEQP# 相同。ACMD001A 是 ACMD001 的子机器,而 RUP5120 是 SLE003 的子机器。

查询结果应该是:

EMEQP#   |  EMCOST  |  EMBOOK  
ACMD001  |  18      |  13  
ACMD002  |  10      |  12  
SLE003   |  23      |  12

我需要知道每台机器的 EMCOST 和 EMBOOK 总数,即父级和任何子级的总和。起初我尝试在 EMLEQP 上使用 group by,但这不起作用,因为它可以在父级上为空。
接下来我尝试使用子查询。主查询选择所有父节点 (WHERE EMLEQP = EMEQP# OR EMLEQP = ''),子查询计算所有机器的总和,其中 EMLEQP 是父节点的 EMEQP#(或为空以包括父节点)。到目前为止,这是我计算 EMCOST 总和的内容。

SELECT EMEQP#, (SELECT SUM(b.emcost) FROM uv_EQPMASFL AS b WHERE (b.emleqp = a.emeqp# AND b.emeqp# <> a.emeqp# OR b.emeqp# = a.emeqp#) 'EMCOST' FROM uv_EQPMASFL a WHERE (EMLEQP = EMEQP# or EMLEQP = '')

此查询有效,但速度极慢。运行它需要超过 15 分钟,我什至还没有添加第二个总和。由于我不能在子查询中使用两列,我需要添加第二个子查询来获得第二个总和。最后,如果我能得到另一列来指示属于父级(包括父级)的机器的数量,我也希望它。

必须有更好、更有效的方法来获取这些数据,但我不知道如何。

【问题讨论】:

    标签: sql-server tsql sql-server-2016


    【解决方案1】:

    使用CTE 而不是nesting select 编写它很容易,如果您没有INDEX 问题,我相信它会在一秒钟内执行大约10k 数据:

    With CTE As (
        SELECT
            emleqp,
            emeqp#,
            SUM(emcost) as EMCOST
        FROM uv_EQPMASFL
        GROUP BY emleqp, emeqp#
    )
    
    SELECT
        EMEQP#, 
        b.EMCOST
    FROM uv_EQPMASFL a
    LEFT JOIN CTE AS b ON b.emleqp = a.emeqp#  AND b.emeqp# <> a.emeqp# OR b.emeqp# = a.emeqp#
    Where a.EMLEQP = a.EMEQP# or a.EMLEQP = ''
    

    请重新检查JOIN 条件,因为ANDOR 的组合需要parenthesis

    【讨论】:

    • 谢谢,但这并没有真正奏效。我得到了很多重复的值,但仍然需要几分钟才能运行。然而,它确实给了我采取另一种方法的想法,并且我能够解决它。
    • @NilsTiebos;如果有帮助,请投票。
    【解决方案2】:

    根据@XAMT 的建议,我采取了另一种方法并能够解决这个问题。
    对于任何有兴趣的人,我首先 SELECT EMLEQP 不为空的数据(因此所有孩子和父母在 EMLEQP 中都有自己的 EMQP#,然后 UNION 带有 SELECT 的 EMLEQP 为空的数据。
    从那个选择中,我选择了另一个SELECT,我GROUP BY EMEQP#

    【讨论】:

    • 自己解决很好,但我用样本数据测试过,效果很好。所以也许你对真实数据或Join condition 有问题,就像我之前说的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 2021-12-30
    • 2013-02-28
    相关资源
    最近更新 更多