我有一个表,其中包含机器上的数据。除其他外,还有(唯一的)设备号(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分钟以上,我什至还没有添加第二笔款项。由于我不能在子查询中使用两列,因此我将需要添加第二个子查询以获取第二个总和。最后,如果我能再获得一列来指示作为父级(包括父级)一部分的计算机的数量,我也希望这样做。
必须有一种更好,更有效的方法来获取此数据,但我不知道如何。
[用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
条件,因为将parenthesis
和AND
组合在一起需要OR
。
根据@XAMT的建议,我采用了另一种方法,并能够解决此问题。对于感兴趣的人,我首先将EMLEQP不为空的数据SELECT
(因此,所有孩子和父母在EMLEQP中具有自己的EMEQP#,然后再将其UNION
的数据为SELECT
,其中EMLEQP为空。从该选择中,我选取另一个SELECT
,我将其GROUP BY
EMEQP#