【问题标题】:Error subquery on materialized view物化视图上的错误子查询
【发布时间】:2017-05-09 18:51:06
【问题描述】:

我正在尝试创建一个物化视图,但是当我运行它时,由于子查询,它向我显示了一个错误。我在 oracle doc 中看到允许子查询在 FROM 和 WHERE 语句的物化视图中使用它们。我把子查询放在这里,你可以帮我解决问题。

    CREATE MATERIALIZED VIEW LOG ON "subscriber" WITH SEQUENCE, ROWID
    ("id", "status", "id_service") 
    INCLUDING NEW VALUES;

    CREATE MATERIALIZED VIEW LOG ON "subscriber_events" WITH SEQUENCE, ROWID
    ("created_at", "id_event", "billed", "percent_billed", "id_service")
    INCLUDING NEW VALUES;

    CREATE MATERIALIZED VIEW LOG ON "subscriber_status" WITH SEQUENCE, ROWID
    ("id_status")
    INCLUDING NEW VALUES;

    CREATE MATERIALIZED VIEW LOG ON "service" WITH SEQUENCE, ROWID
    ("id", "price", "revenue")
    INCLUDING NEW VALUES;


    CREATE MATERIALIZED VIEW "bill_arpu_month_by_service"
    TABLESPACE plat_dat
    BUILD IMMEDIATE
    REFRESH FORCE 
    START WITH sysdate NEXT +1 MONTH 
    ENABLE QUERY REWRITE
    AS

    SELECT * FROM 
    (SELECT created, service, billed, global_user_actives, optin, optout, new_users, dif, 
    global_user_actives - SUM(new_users) OVER (PARTITION BY service ORDER BY created DESC) as actives_S_M, 
    global_user_actives - SUM(new_users) OVER (PARTITION BY service ORDER BY created DESC) + new_users as actives_E_M, 
    round((CASE WHEN (global_user_actives - SUM(new_users) OVER (PARTITION BY service ORDER BY created DESC) + new_users) =0 THEN 0 
    ELSE (billed/(global_user_actives - SUM(new_users) OVER (PARTITION BY service ORDER BY created DESC) + new_users)) * service_mult END),2) arpu

    FROM 
    ( select to_char("created_at", 'yyyymm') "CREATED", AVG("service"."id") service,
    SUM( CASE WHEN "id_event" IN ('1', '5', '3') and "billed" = '1' THEN 1 WHEN "id_event" IN ('6', '4') and "billed" = '1' THEN "percent_billed"/100 ELSE 0 END) AS BILLED, 
    (select count("id") from "subscriber" join "subscriber_status" on "subscriber"."status" = "subscriber_status"."id_status" where "subscriber"."status" = 1 and "subscriber"."id_service" = "service"."id") as global_user_actives, 
    SUM( CASE WHEN "id_event" IN ('1') THEN 1 ELSE 0 END) AS optin, SUM( CASE WHEN "id_event" IN ('2') THEN 1 ELSE 0 END) AS optout, (SUM( CASE WHEN "id_event" IN ('1','3') THEN 1 ELSE 0 END) - SUM( CASE WHEN "id_event" IN ('2') THEN 1 ELSE 0 END)) as new_users, 
    ((select count("id") from "subscriber" join "subscriber_status" on "subscriber"."status" = "subscriber_status"."id_status" where "subscriber"."status" = 1 and "subscriber"."id_service" = "service"."id") - (SUM( CASE WHEN "id_event" IN ('1','3') THEN 1 ELSE 0 END) - SUM( CASE WHEN "id_event" IN ('2') THEN 1 ELSE 0 END))) as dif, 

    (COALESCE( AVG("service"."price")*AVG("service"."revenue")/100 , 0)) as service_mult

    from "subscriber_events" 
    JOIN "service" ON "subscriber_events"."id_service" = "service"."id" 
    where "id_event" IN ('1', '2', '3', '4', '5', '6') 
    group by "service"."id", to_char("created_at", 'yyyymm') order by "service"."id", "CREATED" DESC ) 
    ORDER BY "SERVICE", "CREATED" DESC);


> Error SQL: ORA-22818: expresiones de subconsulta no permitidas aquí
> 22818. 00000 - "subquery expressions not allowed here"  
> *Cause: An attempt was made to use a subquery expression where these are not supported.  
> *Action: Rewrite the statement without the subquery expression.

【问题讨论】:

  • 请在顶部正确使用{}进行编辑

标签: sql oracle


【解决方案1】:

物化视图不支持子查询 - 句号。另外需要注意的是,我相信 Oracle 不支持 ANSI 连接语法,即 JOIN、INNER JOIN 等,并且更喜欢原始的“,”分隔语法,即

/*This syntax is not supported*/
SELECT * 
      FROM TABLE1
INNER JOIN TABLE2
        ON TABLE1.col1 = TABLE2.col2


/*This syntax is preferred*/
SELECT *  FROM 
        TABLE1,
        TABLE2
         WHERE TABLE1.col1 = TABLE2.col2

请参阅here 了解有关快速刷新实体化视图的所有限制

【讨论】:

  • Oracle 确实在连接、外部、内部等方面支持当前的 ANSI 语法,并且已经很长时间了。
  • 我意识到他们确实支持 ANSI。但是,我的意思是在我的评论上下文中,即快速刷新物化视图。我的理解是(至少在 10gR2 中)ansi join 语法不支持快速刷新。我完全愿意在这方面得到纠正。
【解决方案2】:

我最终做的是创建一个没有连接的视图,然后基于该视图创建物化视图并且它有效.. 我向您展示了我所做的事情,以防它出现问题。 谢谢!

日志:

CREATE MATERIALIZED VIEW LOG ON "subscriber" WITH SEQUENCE, ROWID
("id", "status", "id_service") 
INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG ON "subscriber_events" WITH SEQUENCE, ROWID
("created_at", "id_event", "billed", "percent_billed", "id_service")
INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG ON "subscriber_status" WITH SEQUENCE, ROWID
("id_status")
INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG ON "service" WITH SEQUENCE, ROWID
("id", "price", "revenue")
INCLUDING NEW VALUES;

查看:

CREATE OR REPLACE VIEW "bill_arpu_month_view" as
select to_char("created_at", 'yyyymm') "CREATED", AVG("service"."id") service,
SUM( CASE WHEN "id_event" IN ('1', '5', '3') and "billed" = '1' THEN 1 WHEN "id_event" IN ('6', '4') and "billed" = '1' THEN "percent_billed"/100 ELSE 0 END) AS BILLED, 
(select count("id") from "subscriber" join "subscriber_status" on "subscriber"."status" = "subscriber_status"."id_status" where "subscriber"."status" = 1 and "subscriber"."id_service" = "service"."id") as global_user_actives, 
SUM( CASE WHEN "id_event" IN ('1') THEN 1 ELSE 0 END) AS optin, SUM( CASE WHEN "id_event" IN ('2') THEN 1 ELSE 0 END) AS optout, (SUM( CASE WHEN "id_event" IN ('1','3') THEN 1 ELSE 0 END) - SUM( CASE WHEN "id_event" IN ('2') THEN 1 ELSE 0 END)) as new_users, 
((select count("id") from "subscriber", "subscriber_status" where "subscriber"."status" = "subscriber_status"."id_status" and "subscriber"."status" = 1 and "subscriber"."id_service" = "service"."id") - (SUM( CASE WHEN "id_event" IN ('1','3') THEN 1 ELSE 0 END) - SUM( CASE WHEN "id_event" IN ('2') THEN 1 ELSE 0 END))) as dif, 

(COALESCE( AVG("service"."price")*AVG("service"."revenue")/100 , 0)) as service_mult

from "subscriber_events", "service" 
    WHERE "subscriber_events"."id_service" = "service"."id" 
AND "id_event" IN ('1', '2', '3', '4', '5', '6') 
group by "service"."id", to_char("created_at", 'yyyymm') order by "service"."id", "CREATED" DESC ;

实体化视图:

CREATE MATERIALIZED VIEW "bill_arpu_month_by_service"
TABLESPACE plat_dat
BUILD IMMEDIATE
REFRESH FORCE 
AS
SELECT created, service, billed, global_user_actives, optin, optout, new_users, dif, 
global_user_actives - SUM(new_users) OVER (PARTITION BY service ORDER BY created DESC) as actives_S_M, 
global_user_actives - SUM(new_users) OVER (PARTITION BY service ORDER BY created DESC) + new_users as actives_E_M, 
round((CASE WHEN (global_user_actives - SUM(new_users) OVER (PARTITION BY service ORDER BY created DESC) + new_users) =0 THEN 0 
      ELSE (billed/(global_user_actives - SUM(new_users) OVER (PARTITION BY service ORDER BY created DESC) + new_users)) * service_mult END),2) arpu
FROM 
"bill_arpu_month_view"
ORDER BY "SERVICE", "CREATED" DESC;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 2021-09-12
    • 2021-10-24
    • 2022-06-16
    • 2018-07-04
    • 2014-07-03
    • 1970-01-01
    相关资源
    最近更新 更多