【问题标题】:Early (or re-ordered) re-use of derived columns in a query - is this valid ANSI SQL?查询中派生列的早期(或重新排序)重用 - 这是有效的 ANSI SQL 吗?
【发布时间】:2011-01-28 08:36:18
【问题描述】:

这是有效的 ANSI SQL 吗?:

SELECT 1 AS X
       ,2 * X AS Y
       ,3 * Y AS Z

因为 Teradata (12) 可以做到这一点,也可以做到这一点(是的,不是很疯狂):

SELECT 3 * Y AS Z
       ,2 * X AS Y
       ,1 AS X

但是 SQL Server 2005 需要这样的东西:

SELECT  X
       ,Y
       ,3 * Y AS Z
FROM    (
         SELECT X
               ,2 * X AS Y
         FROM   (
                 SELECT 1 AS X
                ) AS X
        ) AS Y

【问题讨论】:

  • 我想知道如果你尝试SELECT 2*y AS x, 2*x AS y会抛出什么错误

标签: sql sql-server teradata ansi-sql


【解决方案1】:

不,它不是有效的 ANSI。 ANSI 假定所有 SELECT 子句项都被一次计算。

我会在 SQL 2005 中将其编写为:

SELECT *
FROM        (SELECT 1 AS X) X
CROSS APPLY (SELECT 2 * X AS Y) Y
CROSS APPLY (SELECT 3 * Y AS Z) Z
;

【讨论】:

  • CTE 的巧妙替代方案 - 我会牢记这一点。不幸的是,Teradata 既不支持堆叠 CTE(我相信它可能支持一个,所以在我的列表中进行调查)也不支持 APPLY 运算符。
  • 当然在 Teradata 中重用别名不是 ANSI SQL,但 CROSS APPLY 也是标准 SQL 的扩展 :-)
【解决方案2】:

在 SQL Server 2005+ 中不需要那么难看。这就是微软引入 CTE 的原因:

WITH T1 AS (SELECT 1 AS X),
     T2 AS (SELECT X, 2 * X AS Y FROM T1)
SELECT X, Y, 3 * Y AS Z FROM T2

或者您可以像 Rob 演示的那样使用 CROSS APPLY - 根据查询的具体情况,这可能适合您,也可能不适合您。

我承认它不如 Teradata 干净,但它并不像子查询版本那么糟糕,而且您问题中的原始 Teradata 示例绝对不是 SQL-92 标准的一部分。

我还要补充一点,在您的原始示例中,XYZ 列在技术上并不是您所说的派生列。至少就 Microsoft 和 ANSI 而言,它们只是别名,一个别名不能引用另一个别名,直到它真正变成一个列(即通过子查询或 CTE)。 p>

【讨论】:

  • 我们通常在 SQL Server 中使用多个堆叠的 CTE。不幸的是,它们在 Teradata 中是不允许的 ;-( 我试图找到一个中间立场。我发现当你不嵌套并使用这个技巧时,Teradata 的性能要好得多,但它让我担心它可能无法继续工作,如果将来在 Teradata 中中断,我最好将我的 CTE 转换为嵌套。
猜你喜欢
  • 1970-01-01
  • 2022-09-22
  • 1970-01-01
  • 2021-08-20
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多