如何在同一个 table 上使用 apply 2 次?

How do I use apply 2 times on the same table?

这只是一个易于重现的例子。 正如 gslamed 所建议的那样,有一种解决方案可以避免使用两次应用。但这不是我需要的。我需要使用两次申请。

在这个例子中,我想取集合的第一个元素 (t.b) 在 v.c

WITH
    s (a, b)
    AS
        (SELECT 1,  'ff' FROM DUAL
         UNION ALL
         SELECT 1,  'ee' FROM DUAL
         UNION ALL
         SELECT 1,  'ee' FROM DUAL
         UNION ALL
         SELECT 2,  'ee' FROM DUAL),
    t (a, b)
    AS
        (  SELECT s.a, COLLECT (s.b)
             FROM s
         GROUP BY s.a),
    v (a, b, c)
    AS
        (SELECT t.a, t.b, tb.c
           FROM t
                OUTER APPLY (SELECT x.COLUMN_VALUE     c
                               FROM TABLE (t.b) x
                              FETCH FIRST 1 ROW ONLY) tb)
SELECT *
  FROM v;

它正在工作。

然后我在数v.c

中有多少个元素
WITH
    s (a, b)
    AS
        (SELECT 1, 'ff' FROM DUAL
         UNION ALL
         SELECT 1, 'ee' FROM DUAL
         UNION ALL
         SELECT 1, 'ee' FROM DUAL
         UNION ALL
         SELECT 2, 'ee' FROM DUAL),
    t (a, b)
    AS
        (  SELECT s.a, COLLECT (s.b)
             FROM s
         GROUP BY s.a),
    v (a, b, c)
    AS
        (SELECT t.a, t.b, tb.c
           FROM t
                OUTER APPLY (SELECT count(*)     c
                               FROM TABLE (t.b) x
                              ) tb)
select * from v

现在我想要第一个元素以及 v.c 和 v.d

中有多少个元素
WITH
    s (a, b)
    AS
        (SELECT 1, TO_CLOB ('ff') FROM DUAL
         UNION ALL
         SELECT 1, TO_CLOB ('ee') FROM DUAL
         UNION ALL
         SELECT 1, TO_CLOB ('ee') FROM DUAL
         UNION ALL
         SELECT 2, TO_CLOB ('ee') FROM DUAL),
    t (a, b)
    AS
        (  SELECT s.a, COLLECT (s.b)
             FROM s
         GROUP BY s.a),
    v (a, b, c)
    AS
        (SELECT t.a, t.b, tb.c
           FROM t
                OUTER APPLY (SELECT x.COLUMN_VALUE,count(*)     c
                               FROM TABLE (t.b) x
                              FETCH FIRST 1 ROW ONLY) tb)
select * from v

ORA-00937: not a single-group group function

睡不着,这很正常。我没有使用分组依据 .

因此我想用 v.

中的第二个子选择来计算

我试过两次加t外申请。但它不起作用

WITH
    s (a, b)
    AS
        (SELECT 1, TO_CLOB ('ff') FROM DUAL
         UNION ALL
         SELECT 1, TO_CLOB ('ee') FROM DUAL
         UNION ALL
         SELECT 1, TO_CLOB ('ee') FROM DUAL
         UNION ALL
         SELECT 2, TO_CLOB ('ee') FROM DUAL),
    t (a, b)
    AS
        (  SELECT s.a, COLLECT (s.b)
             FROM s
         GROUP BY s.a),
    v (a, b, c,d)
    AS
        (SELECT t.a, t.b, tb.c,tb2.d
           FROM t
                OUTER APPLY (SELECT x.COLUMN_VALUE     c
                               FROM TABLE (t.b) x
                              FETCH FIRST 1 ROW ONLY) tb)
                OUTER APPLY (SELECT count(*)     d
                               FROM TABLE (t.b) x
                              ) tb2)

select * from v

ORA-00928: missing SELECT keyword

如何使用2次外部应用?

code

使用这个:

WITH
    s (a, b)
    AS
        (SELECT 1, TO_CLOB ('ff') FROM DUAL
         UNION ALL
         SELECT 1, TO_CLOB ('ee') FROM DUAL
         UNION ALL
         SELECT 1, TO_CLOB ('ee') FROM DUAL
         UNION ALL
         SELECT 2, TO_CLOB ('ee') FROM DUAL),
    t (a, b)
    AS
        (  SELECT s.a, COLLECT (s.b)
             FROM s
         GROUP BY s.a),
    v (a, b, c)
    AS
        (SELECT t.a, t.b, tb.c
           FROM t
                OUTER APPLY (SELECT x.COLUMN_VALUE,count(*) over()    c
                               FROM TABLE (t.b) x
                              FETCH FIRST 1 ROW ONLY) tb)
select * from v

你只是多了一个右括号;当你有这个:

    AS
        (SELECT t.a, t.b, tb.c,tb2.d
           FROM t
                OUTER APPLY (SELECT x.COLUMN_VALUE     c
                               FROM TABLE (t.b) x
                              FETCH FIRST 1 ROW ONLY) tb)
--------------------------------------------------------^

... 我标记的 ) 结束了 with 子句。但是当你把它改成这样时:

    AS
        (SELECT t.a, t.b, tb.c,tb2.d
           FROM t
                OUTER APPLY (SELECT x.COLUMN_VALUE     c
                               FROM TABLE (t.b) x
                              FETCH FIRST 1 ROW ONLY) tb)
--------------------------------------------------------^
                OUTER APPLY (SELECT count(*)     d
                               FROM TABLE (t.b) x
                              ) tb2)
-----------------------------------^

.. 您保留了结束 CTE 的右括号,因此第二个 outer apply 不在有效位置。只需删除第一个标记为 ) 并保留第二个标记为 ).

db<>fiddle


对于复杂的查询,我倾向于缩进括号以使此类更加明显 - 所以第一个看起来不错:

    AS
    (
       SELECT t.a, t.b, tb.c,tb2.d
       FROM t
       OUTER APPLY (
         SELECT x.COLUMN_VALUE c
         FROM TABLE (t.b) x
         FETCH FIRST 1 ROW ONLY
       ) tb
    )

但是第二个没有:

    AS
    (
       SELECT t.a, t.b, tb.c,tb2.d
       FROM t
       OUTER APPLY (
         SELECT x.COLUMN_VALUE c
         FROM TABLE (t.b) x
         FETCH FIRST 1 ROW ONLY
       ) tb
    )
    OUTER APPLY (
      SELECT count(*) d
      FROM TABLE (t.b) x
    ) tb2
  )

更明显的应该是:

    AS
    (
       SELECT t.a, t.b, tb.c,tb2.d
       FROM t
       OUTER APPLY (
         SELECT x.COLUMN_VALUE c
         FROM TABLE (t.b) x
         FETCH FIRST 1 ROW ONLY
       ) tb
      OUTER APPLY (
        SELECT count(*) d
        FROM TABLE (t.b) x
      ) tb2
    )