物化视图上的错误子查询

时间:2013-11-27 11:06:03

标签: sql oracle

我试图创建一个物化视图,但是当我运行它时,它会因为子查询而显示错误。我在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.

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

我最终做的是创建一个没有连接的视图,然后根据该视图创建物化视图并且它有效..我告诉你我做了什么以防万一。 谢谢!

日志:

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;

VIEW:

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;