UNION ALL与CONNECT BY LEVEL生成行

时间:2009-10-21 13:35:00

标签: sql oracle optimization

我想知道哪个是将任意字符串转换为列的更好/更快/更有效的方法:

UNION ALL

SELECT my_field,
       CASE WHEN my_field = 'str1'
            THEN ...
            ...
       END,
       ...
FROM (
       SELECT 'str1' AS my_field FROM DUAL
       UNION ALL
       SELECT 'str2' AS my_field FROM DUAL
       UNION ALL
       SELECT 'str3' AS my_field FROM DUAL
     ),
     ...

CONNECT BY LEVEL

SELECT CASE WHEN rowno = 1
            THEN 'str1'
            ...
       END AS my_field,
       CASE WHEN rowno = 1
            THEN ...
            ...
       END,
       ...
FROM (
       SELECT ROWNUM rowno
       FROM DUAL
       CONNECT BY LEVEL <= 3
     ),
     ...

我倾向于使用UNION ALL版本,只因为它使最外面的SELECT变得更简单:我不需要做第二个CASE语句来获得所需的字符串值。查看WHEN my_field = 'str1'而非WHEN rowno = 1更具可读性。我询问CONNECT BY LEVEL版本的唯一原因是因为它是在Example of Data Pivots in SQL (rows to columns and columns to rows)中建议的(参见“从两行到六行(一列到一行到一行)”部分。)

我只有SELECT访问我正在使用的Oracle数据库,因此无法运行EXPLAIN PLAN。我之前也尝试过使用WITH ... AS,但没有运气。

2 个答案:

答案 0 :(得分:1)

除了最微不足道的行之外,我会使用connect by。没有解释计划虽然很痛苦......你真的把手绑在那里。我真的很想知道优化者对基数的估计是什么。

答案 1 :(得分:1)

我认为你混淆了“SQL中的数据枢轴示例(行到列和列到行)”中使用的目的UNION ALL和CONNECT BY方法“

您问题中的UNION ALL用于将具有单个列的多行转换为具有多列的单行:

label, 1, val1
label, 2, val2
label, 3, val3

label, val1, val2, val3

CONNECT BY子查询用于将具有多列的单个行转换为具有单列的多行,因此它使用生成器子查询来乘以现有数据集:

label, val1, val2, val3 
+
1
2
3

结果:

label, 1, val1, val2, val3
label, 2, val1, val2, val3
label, 3, val1, val2, val3

转化为:

label, 1, val1
label, 2, val2
label, 3, val3