1

我在 Oracle 上下文中有 3 个表,我们称它们t1, t2, t3为具有以下结构:

  • t1 : t1_ID, t1_name, ...
  • t2 : t1_ID, t3_name, ...
  • t3 : t3_name, randomCol1, randomCol2, randomCol3, ...

我想要的是一个给我这样的结果的查询:

t0_name | 随机数

所以我做了这个查询:

      SELECT t1.t1_name, t3.randomCol1 AS randomCol
      FROM t1
      JOIN t2 ON t1.t1_ID=t2.t1_ID
      JOIN t3 ON t2.t3_name=t3.t3_name
      WHERE t3.randomCol1 LIKE '_%'
    UNION
      SELECT t1.t1_name, t3.randomCol2 AS randomCol
      FROM t1
      JOIN t2 ON t1.t1_ID=t2.t1_ID
      JOIN t3 ON t2.t3_name=t3.t3_name
      WHERE t3.randomCol2 LIKE '_%'
    UNION
      SELECT t1.t1_name, t3.randomCol3 AS randomCol
      FROM t1
      JOIN t2 ON t1.t1_ID=t2.t1_ID
      JOIN t3 ON t2.t3_name=t3.t3_name
      WHERE t3.randomCol3 LIKE '_%'

因为我希望 randomCols 的所有值都以单列开头,_并与链接到它们的 t1_name 配对。为了提供更多的信息,randomCol1 和 randomCol2 几乎相同(它们都不是同时为 null 并且具有几乎相同的值),而 randomCol3 通常为 null。


我知道这在性能方面很糟糕,所以我试图改进它。

因此,我在网上搜索了各种优化此解决方案的方法(例如使用 UNION ALL 之类的东西),但没有给我想要的确切结果。

所以我的问题如下: 您知道如何优化此查询吗?

问候

4

3 回答 3

2

当您执行unionorunion all时,Oracle 可能会多次执行子查询。unpivot您可以使用或使用 a来解决此问题,cross join如下所示:

SELECT t1.t1_name,
       (case when n.n = 1 then t3.randomCol1
             when n.n = 2 then t3.randomCol2
             when n.n = 3 then t3.randomCol3
        end) AS randomCol
FROM t1 JOIN
     t2
     ON t1.t1_ID=t2.t1_ID JOIN
     t3
     ON t2.t3_name=t3.t3_name cross join
     (select 1 as n from dual union all select 2 from dual union all select 3) n
where n.n = 1 and LEFT(t3.randomCol1, 1) = '_' or
      n.n = 2 and LEFT(t3.randomCol2, 1) = '_' or
      n.n = 3 and LEFT(t3.randomCol3, 1) = '_'

我将 替换为like因为left'_'的通配符like

于 2013-04-18T15:37:34.467 回答
2

一种可能的变体:

  select * from
  (SELECT t1.t1_name, 
          case l.l
              when 1 then t3.randomCol1 
              when 2 then t3.randomCol2 
              when 3 then t3.randomCol3
          end AS randomCol
   FROM (select level l from dual connect by level <= 3) l
   CROSS JOIN t1
   JOIN t2 ON t1.t1_ID=t2.t1_ID
   JOIN t3 ON t2.t3_name=t3.t3_name
   WHERE '_' in (substr(t3.randomCol1,1,1),
                 substr(t3.randomCol2,1,1),
                 substr(t3.randomCol3,1,1))
  ) where randomCol like '_%'
于 2013-04-18T15:42:44.137 回答
1

在 SQL Server 中,它类似于

SELECT t0_name, randomCol
FROM (SELECT t0_name, randomCol1, randomCol2, etc)
      FROM t0
      JOIN t01 ON t0.t0_ID=t1.t0_ID
      JOIN t1 ON t01.t1_name=t1.t1_name) p
UNPIVOT (randomCol FOR items in (randomCol1, randomCol2, etc)) unpvt
WHERE randomCol like '_%'

我认为在 Oracle 中也是一样的:参见这篇文章

于 2013-04-18T15:32:50.523 回答