在具有父子关系的同一表上具有多个子选择的选择

问题描述 投票:0回答:2

我有一个表,其中包含机器上的数据。除其他外,还有(唯一的)设备号(EMEQP#),财务成本(EMCOST),当前值(EMBOOK)和设备链接(EMLEQP)的列。某些计算机由其他几台计算机组成,通过将“父”计算机的EMEQP#放在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
2个回答
0
投票

[用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条件,因为将parenthesisAND组合在一起需要OR


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.