我优化报告系统的SQL查询,用户可以选择列但是表是固定的:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<target>
<copy file="target/${project.artifactId}-exec.jar" tofile="../../docker/${project.artifactId}.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
我想删除不必要的表并动态生成整个查询:
-- Dynamically generated
SELECT t1.c4, t4.c8
-- Static
FROM t1
INNER JOIN t2 ON t1.id=t2.t1_id
INNER JOIN t3 ON t1.id=t3.t1_id
INNER JOIN t4 ON t2.id=t4.t2_id
INNER JOIN t5 ON t4.id=t5.t4_id
/*...*/;
为了找出依赖关系,我在Packagist中进行了搜索,找到了marcj/topsort和topological sorting,其工作原理如下:
-- Dynamically generated
SELECT t1.c4, t4.c8
FROM t1
INNER JOIN t2 ON t1.id=t2.t1_id
INNER JOIN t4 ON t2.id=t4.t12_id;
$sorter = new StringSort();
$sorter->add('t1');
$sorter->add('t2', array('t1'));
$sorter->add('t3', array('t1'));
$sorter->add('t4', array('t2'));
$sorter->add('t5', array('t4'));
print_r($sorter->sort());
但我真正需要的是一种方法,该方法需要实际需要的第一级表,并计算出符合依赖性的最小表集,如:
Array
(
[0] => t1
[1] => t2
[2] => t3
[3] => t4
[4] => t5
)
// Sample interface and expected output
$query->getRequiredTables(array('t1', 't4'));
我不能仅使用第一级表格提供Array
(
[0] => t1
[1] => t2
[2] => t4
)
,因为我会得到->add()
。
在这里,我迷失了方向。甚至拓扑排序是正确的工具吗?
答案 0 :(得分:1)
首先,为表创建依赖关系树。例如,在您的情况下,它将是:
1
/ \
2 3
|
4
|
5
以root身份从所需的表列表中选择任何表。 例如,如果需要表2和表3,则可以选择2作为根并获取以下树:
2
/ \
4 1
| |
5 3
现在从根遍历树,当你点击任何所需的表(在我们的例子中为3)时,将堆栈中的所有表添加到结果中。例如,当您在节点3中时,您的堆栈为[2,1,3],您将所有这些节点添加到结果中。
说,使用相同的依赖树用户请求表1,3和4.在这种情况下,您将1作为根,当您到达节点4时,您的堆栈是[1,2,4]并且当您点击节点时3你的筹码是[1,3]。结果是[1,2,3,4]。
遍历树的示例代码(不是以任何特定语言,仅作为示例)。
function dfs(node) {
bool include = requiredTables.contains(node)
for each child of node {
if dfs(child) {
include = true;
}
}
if (include) result.add(node);
return include;
}