提高查询性能和可维护性

时间:2020-03-03 00:05:36

标签: sql string oracle group-by count

我有这样的查询:

select Table1.column1 AS CODE, COUNT(DINSTINCT(Table2.column1 || '|' || Table2.column2)) AS COUNT
FROM   Table2
INNER JOIN Table3 ON Table3.referenceColumn = Table2.referenceColumn
INNER JOIN Table1 ON Table1.referenceColumn = Table2.referenceColumn
WHERE
....
AND Table1.column1 <> ''

查询的输出将是这样的,基本上是一个CODE和相应的COUNT,例如:

CODE    COUNT
ref002   3
ref003   1

在第一个查询之后,我有一个foreach,它将对上面的查询结果进行迭代。在foreach内,针对每个查询结果 上面,我想要获取一些Table3中可用的信息,基本上,我想要每个CODE(Table1.Column1)的Table3.column1中的所有值。因此,在foreach内,我还有另一个查询来获取每个迭代结果的Table3.column:

select Table3.column1
FROM   Table3
INNER JOIN Table3 ON Table3.referenceColumn = Table2.referenceColumn
INNER JOIN Table1 ON Table1.referenceColumn = Table2.referenceColumn
WHERE .... 
AND Table1.column1 = (equal to a parameter (Table1.column1) that is available in each foreach iteration)

这样,我可以获取第一个查询的每个Table1.column1(每个CODE)的所有Table3.column1值。

怀疑

两个查询几乎相同。 foreach之前的查询和foreach内部的查询之间的唯一区别是在SELECT部分和WHERE中,基本上是其中仅具有附加条件的地方。因此,这两个查询在性能和可维护性方面都不太好,因为两个查询几乎相同。因此,应该有可能在第一个查询中获得所有必要的信息,而不是在foreach内进行第二个查询。

您知道在第一个查询中需要进行哪些更改,除了返回CODE和COUNT之外,还为每个CODE返回Table3.column1中的所有值?这样就可以删除foreach内部的查询,并获得仅一个查询(第一个查询)所需的所有内容?第一个查询的必要输出应类似于:

CODE     COUNT     IDNUMBERS
ref002    3         ab00, cd00
ref003    1         ef00

1 个答案:

答案 0 :(得分:3)

您的策略为每个代码生成一个查询,再为初始查询生成一个查询,因此确实效率低下。

一个简单的选择是在原始查询中使用字符串聚合函数来生成附加列。

在Oracle中,您可以为此使用listagg()

select 
    t1.column1 as code, 
    count(distinct t2.column1 || '|' || t2.column2) as cnt,
    listagg(t3.column1) idnumbers
from   table2 t2
inner join table3 t3 on t3.referencecolumn = t2.referencecolumn
inner join table1 t1 on t1.referencecolumn = t1.referencecolumn
where ...
group by t1.column1

listagg()具有用于格式化,重复管理和排序的各种选项-您可以找到详细信息in the documentation