【问题标题】:Oracle nested query reference parent column more than 1 level deepOracle 嵌套查询引用父列深度超过 1 级
【发布时间】:2015-04-15 18:56:28
【问题描述】:

我知道对于具有超过 1 级深度的引用父级的嵌套查询的 oracle 限制要求我们展示一些创造力,但我真的坚持这一点。

我需要通过选择包含电视节目的名为“PROGRAM”的表的字段并在视图中包含一个名为“PRODUCERS”的字段来创建一个视图,该字段必须是电视节目中涉及的所有制作人的串联。

因此,我最终在视图创建过程中处理了 3 个表:

节目(id_program,导演,...)

PRODUCER (id_producer, name, ...)

PROGRAM_PRODUCER (id_producer, id_program)

这是创建视图的查询:

DROP VIEW VIEW_PROGRAM;

CREATE OR REPLACE FORCE VIEW VIEW_PROGRAM
(
   PRGM_ID,
   FORMAT_TITLE,
   GENRE,
   TYPE,
   DIRECTOR,
   ORIGIN1,
   PRODUCER,
   BROADCAST_TIME,
   DURATION,
   CHANNEL,
   LOCAL_TITLE
)
AS
   SELECT program.id_program AS prgm_id,
          program.original_title AS format_title,
          genres.genre AS genre,
          genres.type_ AS TYPE,
          program.director AS director,
          program.origin1,

          (Select listagg(producer,' / ') WITHIN GROUP (order by 'producer') 
          FROM  (SELECT P.PRODUCER FROM PRODUCERS P WHERE P.ID IN 
          (SELECT PP.ID_PRODUCER FROM PROGRAM_PRODUCER PP WHERE PP.ID_PROGRAM = 19927))) AS producer,

          program.broadcast_time AS broadcast_time,
          program.duration AS duration,
          channels.channel AS channel,
          program.local_title
     FROM program
          LEFT JOIN genres
             ON program.p_genre = genres.id_genre
          LEFT JOIN countries
             ON program.p_country = countries.id_country
          LEFT JOIN channels
             ON program.p_channel = channels.id_channel;   

我的问题在于这部分:

          (Select listagg(producer,' / ') WITHIN GROUP (order by 'producer') 
          FROM  (SELECT P.PRODUCER FROM PRODUCERS P WHERE P.ID IN 
          (SELECT PP.ID_PRODUCER FROM PROGRAM_PRODUCER PP WHERE PP.ID_PROGRAM = 19927))) AS producer,

除了值“19927”实际上应该引用“prgm_id”,但这显然会抛出未知标识符异常..

我花了很多时间尝试将 where 子句拉到其他地方,但没有成功,非常感谢任何帮助。

【问题讨论】:

  • 您为什么在该部分使用IN 和另一个子查询,而不是将producers 加入program_producer?为什么要按常数而不是列值排序-我想这只是一个错误?我不确定你为什么有一个子查询,并且没有加入主查询中的第四个表并使用group by 子句....
  • 无论我使用 join 还是 in 子句,它都不会改变我的 listagg 函数需要嵌套查询的事实,因此在引用 prgm_id 时会出现同样的问题
  • 连接将摆脱一层嵌套;你已经有了一个额外的冗余级别。您可以将其简化为单个子查询,然后可以看到外部查询的列值;或者在主查询中使用额外的连接和 group by 来消除子查询。
  • 你说得对,我只是没看到...谢谢!

标签: oracle nested subquery


【解决方案1】:

您不需要嵌套的子查询;您可以在单个子查询级别中用连接替换该部分,该子查询仍然可以引用程序:

      (Select listagg(p.producer,' / ') WITHIN GROUP (order by p.producer) 
        FROM PRODUCERS P
        JOIN PROGRAM_PRODUCER PP ON P.ID_PRODUCER = PP.ID_PRODUCER
        WHERE PP.ID_PROGRAM = program.id_program) AS producer,

或者您可以通过在主外部连接序列中包含额外的表并添加包含所有其他选择列表项的group by 子句来完全删除子查询:

   SELECT program.id_program AS prgm_id,
          program.original_title AS format_title,
          genres.genre AS genre,
          genres.type_ AS TYPE,
          program.director AS director,
          program.origin1,
          listagg(producers.producer,' / ')
            WITHIN GROUP (order by producers.producer) AS producer,
          program.broadcast_time AS broadcast_time,
          program.duration AS duration,
          channels.channel AS channel,
          program.local_title
     FROM program
          LEFT JOIN program_producer
             ON program_producer.id_program = program.id_program
          LEFT JOIN producers
             ON producers.id_producer = program_producer.id_producer
          LEFT JOIN genres
             ON program.p_genre = genres.id_genre
          LEFT JOIN xcountries
             ON program.p_country = xcountries.id_country
          LEFT JOIN channels
             ON program.p_channel = channels.id_channel
GROUP BY program.id_program,
          program.original_title,
          genres.genre,
          genres.type_,
          program.director,
          program.origin1,
          program.broadcast_time,
          program.duration,
          channels.channel,
          program.local_title;

SQL fiddle 显示查询没有错误;修复部分组成的架构并添加一些数据以检查它们是否获得了您期望的结果。

【讨论】:

  • 第二个解决方案看起来很简单。我不知道为什么我能看到它,我猜 listagg 的事情让我迷失了方向。还是非常感谢
  • 由于我不熟悉如何使用 WITHIN GROUP,请您帮我弄清楚当 listagg 函数中未选择“row_order”时如何“按 producer.row_order 排序”?
  • @Marc - 它不需要在选择列表或 group by 子句中;你可以把它改成WITHIN GROUP (order by producers.row_order) AS producer。当然,假设这实际上是该表中的列名。想知道它是否应该是来自program_producers 的贷记订单或类似订单。
  • 再次抱歉,我把它弄混了,row_order 在表 program_producer 而不是 producer,因此正确的语法是“按 pp.row_order 排序”。感谢您的积极反应
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 2020-02-21
  • 2011-08-27
相关资源
最近更新 更多