SQL Query删除循环冗余

时间:2013-08-20 13:51:00

标签: sql oracle sankey-diagram

我有一个看起来像这样的表:

  Column A   |    Column   B    |     Counter
---------------------------------------------
      A      |       B          |       53
      B      |       C          |       23
      A      |       D          |       11
      C      |       B          |       22

我需要移除最后一行,因为它循环到第二行。似乎无法弄清楚如何做到这一点。

修改

有一个索引日期字段。这是为Sankey图。示例表中的数据实际上是查询的结果。基础表有:

date   | source node | target node | path count 

构建表的查询是:

SELECT source_node, target_node, COUNT(1) 
FROM sankey_table 
WHERE TO_CHAR(data_date, 'yyyy-mm-dd')='2013-08-19' 
GROUP BY source_node, target_node 

在示例中,最后一行C到B向后移动,我需要忽略它,否则Sankey将不会显示。我只需要显示前进路径。

3 个答案:

答案 0 :(得分:1)

从图表中删除元组(source_node,target_node)不按字母顺序排序且对称行存在的所有边缘应该可以提供您想要的内容:

DELETE 
FROM sankey_table t1
WHERE source_node > target_node
AND EXISTS (
  SELECT NULL from sankey_table t2
  WHERE t2.source_node = t1.target_node
    AND t2.target_node = t1.source_node)

如果您不想删除它们,只需在查询中使用此WHERE子句来生成图表的输入。

答案 1 :(得分:0)

DELETE FROM yourTable
where [Column A]='C'

鉴于这些都是你的行

修改

我建议您尽可能清理源数据,即删除向后调用的行,如果这些行在您的注释中声明不正确。

答案 2 :(得分:0)

如果您可以调整表的填充方式,则可以将您正在使用的查询更改为仅首先检索第一个方向(该日期)的值,并进行一些分析操作:< / p>

SELECT source_node, target_node, counter FROM (
  SELECT source_node,
    target_node,
    COUNT(*) OVER (PARTITION BY source_node, target_node) AS counter,
    RANK () OVER (PARTITION BY GREATEST(source_node, target_node),
      LEAST(source_node, target_node), TRUNC(data_date)
        ORDER BY data_date) AS rnk
  FROM sankey_table 
  WHERE TO_CHAR(data_date, 'yyyy-mm-dd')='2013-08-19' 
)
WHERE rnk = 1;

内部查询获取您现在收集的相同数据但添加排名列,对于给定日期的任何顺序,任何源/目标对的第一行将为1。外部查询然后忽略其他所有内容。

如果你每天截断并重新填充它,这可能是物化视图的候选者。

如果您无法更改中间表但仍可以查看基础表,则可以使用相同的想法加入其中;假设您要查询的表名为sankey_agg_table

SELECT sat.source_node, sat.target_node, sat.counter
FROM sankey_agg_table sat
JOIN (SELECT source_node, target_node,
    RANK () OVER (PARTITION BY GREATEST(source_node, target_node),
      LEAST(source_node, target_node), TRUNC(data_date)
        ORDER BY data_date) AS rnk
  FROM sankey_table) st
ON st.source_node = sat.source_node
AND st.target_node = sat.target_node
AND st.rnk = 1;

SQL Fiddle demos