在我的previous question,我可以解决如何获取位置层次 struct .但当我try 与系统集成时,似乎有另一个问题

所以我有两张桌子,像

位置(约20,000条记录)

id Name is_active level1 level2 level3 level4
1 A true A null null null
2 A>B true A B null null
3 A>B>C true A B C null
4 A>B>C>D true A B C D
5 X true X null null null

日志(log)(约500万条记录)

id Name location_id
1 log 001 3
2 log 002 5

因此,目标是我想获取的位置层次 struct ,其中只有日志(log). 问题是,当我try 连接日志(log)表时,它有一个性能问题.查询似乎需要10多分钟

下面是我的查询看起来像demo 我正在try 这个查询

SELECT *
FROM   location
START WITH id IN (SELECT DISTINCT location_id FROM log_response)
CONNECT BY PRIOR name
           = name || '>' || COALESCE(PRIOR level4, PRIOR level3, PRIOR level2)
ORDER BY NAME

WITH cte(location_id) AS (
     SELECT DISTINCT location_id FROM log_response
)
SELECT *
FROM   location
START WITH id IN (SELECT location_id FROM cte)
CONNECT BY PRIOR name
           = name || '>' || COALESCE(PRIOR level4, PRIOR level3, PRIOR level2)
ORDER BY NAME

P/S以上示例的查询预期应返回(1,2,3,5)中的位置HAD ID

id Name is_active level1 level2 level3 level4
1 A true A null null null
2 A>B true A B null null
3 A>B>C true A B C null
5 X true X null null null

非常感谢!

推荐答案

您可以使用EXISTS(而不是INDISTINCT):

SELECT *
FROM   location l
START WITH EXISTS(SELECT 1 FROM log WHERE location_id = l.id)
CONNECT BY name = SUBSTR(PRIOR name, 1, INSTR(PRIOR name, '>', -1) - 1)

其中,对于样本数据:

CREATE TABLE location (id, Name, is_active, level1, level2, level3, level4) AS
SELECT 1, 'A',       'true', 'A', null, null, null FROM DUAL UNION ALL
SELECT 2, 'A>B',     'true', 'A', 'B',  null, null FROM DUAL UNION ALL
SELECT 3, 'A>B>C',   'true', 'A', 'B',  'C',  null FROM DUAL UNION ALL
SELECT 4, 'A>B>C>D', 'true', 'A', 'B',  'C',  'D'  FROM DUAL UNION ALL
SELECT 5, 'X',       'true', 'X', null, null, null FROM DUAL;

CREATE TABLE log (id, Name, location_id) AS
SELECT 1, 'log 001', 3 FROM DUAL UNION ALL
SELECT 2, 'log 002', 5 FROM DUAL;

输出:

ID NAME IS_ACTIVE LEVEL1 LEVEL2 LEVEL3 LEVEL4
3 A>B>C true A B C null
2 A>B true A B null null
1 A true A null null null
5 X true X null null null

或者:

SELECT DISTINCT *
FROM   location l
START WITH EXISTS(SELECT 1 FROM log WHERE location_id = l.id)
CONNECT BY 
       PRIOR level1 = level1
AND    (  (   level2 IS NULL AND level3 IS NULL AND level4 IS NULL
          AND PRIOR level2 IS NOT NULL AND PRIOR level3 IS NULL AND PRIOR level4 IS NULL
          )
          OR (   PRIOR level2 = level2
             AND ( (   level3 IS NULL AND level4 IS NULL
                   AND PRIOR level3 IS NOT NULL AND PRIOR level4 IS NULL
                   )
                 OR (   PRIOR level3 = level3
                    AND level4 IS NULL AND PRIOR level4 IS NOT NULL
                    )
                 )
              )
      )

fiddle

Sql相关问答推荐

使用交叉应用透视表在SQL中转换分段时间段&

PostgreSQL:如果发现多行具有相似列值,则跳过 Select 行

如何用3个(半)固定位置建模团队,并有效地搜索相同/不同的团队?

不可能在SQL MERGE子句中引发异常

如何在SQL中按每个子组的顺序更新数据?

如何根据给定条件PostgreSQL迭代减少组中的行数

重新组合已排序的日期范围

每年独特口味的冰淇淋数量

PATINDEX中与[A-Z]匹配(U除外)的正则表达式

Postgres SQL查询从字符串中获取邮箱地址

group-by-clause具有特定列,而不是oracle的toad中的all

SQL根据另一列的顺序和值获取组中的最后一列

Spark / Hive:如何获取列中正值的百分比?

JSON对象查询SQL服务器

根据开始时间和结束时间计算has_impact字段

在 BigQuery 数据集中查找表大小和占总数据集大小的百分比

在给定列中具有特定值的行与 SQL 中的总行数的比率

SQL 查询以填充单个列中的所有值

SQL中所有先前日期的累计总和

使用 json_agg 从 SQL 查询获取 [null] 响应