【问题标题】:Oracle SQL Partition range all instead of range singleOracle SQL 分区范围全部而不是范围单一
【发布时间】:2020-12-10 13:08:08
【问题描述】:

我按日期创建了一个分区表,我在其中划分了 createdate(然后客户创建了一个帐户)。

CREATE TABLE PARTITIONED_customer (
                        customerId number(10) GENERATED AS IDENTITY, 
                        firstName  varchar2(50), 
                        lastName   varchar2(50), 
                        email      varchar2(50), 
                        createDate date, 
                        active     char(1),
                        PRIMARY KEY (customerId))
                        PARTITION BY RANGE (createDate)
                        INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
                        (PARTITION first_quater_2018 VALUES LESS THAN(TO_DATE('01-04-2018','dd-MM-yyyy')),
                        PARTITION second_quater_2018 VALUES LESS THAN(TO_DATE('01-07-2018','dd-MM-yyyy')),
                        PARTITION third_quater_2018 VALUES LESS THAN(TO_DATE('01-10-2018','dd-MM-yyyy')),
                        PARTITION fourth_quater_2018 VALUES LESS THAN(TO_DATE('01-01-2019','dd-MM-yyyy')),
                        PARTITION first_quater_2019 VALUES LESS THAN(TO_DATE('01-04-2019','dd-MM-yyyy')),
                        PARTITION second_quater_2019 VALUES LESS THAN(TO_DATE('01-07-2019','dd-MM-yyyy')),
                        PARTITION third_quater_2019 VALUES LESS THAN(TO_DATE('01-10-2019','dd-MM-yyyy')),
                        PARTITION fourth_quater_2019 VALUES LESS THAN(TO_DATE('01-01-2020','dd-MM-yyyy')));

这是我想知道客户何时创建帐户的 SQL 查询。我知道查询不完全正确,提前抱歉

select c.createdate, c.firstname, c.lastname, round(sum(p.amount)) as spentmoney
from PARTITIONED_customer c
join PARTITIONED_rental r
on c.customerid = r.customerid
join PARTITIONED_payment_amount p
on p.rentalid = r.rentalid
where  c.createdate BETWEEN TO_DATE('01-05-2019','dd-MM-yyyy') 
AND TO_DATE('01-06-2019','dd-MM-yyyy') 
or (select round(sum(pp.amount)) from PARTITIONED_payment_amount pp
        join PARTITIONED_rental rr
        on rr.rentalid = pp.rentalid
        where rr.customerid=c.customerid) < 50 
group by c.firstname, c.lastname,c.createdate
order by c.firstname, c.lastname;

解释器显示所有分区范围,而不是单个。怎么解决?

我用一个简单的查询自己检查了分区,没问题。所以,我认为查询本身有问题。

【问题讨论】:

    标签: sql oracle query-optimization database-partitioning


    【解决方案1】:

    您的查询正在 PARTITIONED_CUSTOMER 上执行 TABLE ACCESS FULL,因此它当然必须搜索所有分区。我建议在分区键上创建索引:

    CREATE INDEX PARTITIONED_CUSTOMER_1
      ON PARTITIONED_CUSTOMER (CREATEDATE)
      LOCAL;
    

    如果您真的愿意,可以在查询中指定 PARTITION 子句:

    select c.createdate, c.firstname, c.lastname, round(sum(p.amount)) as spentmoney
      from PARTITIONED_customer PARTITION (second_quater_2019) c
      INNER join PARTITIONED_rental r
        on c.customerid = r.customerid
      INNER join PARTITIONED_payment_amount p
        on p.rentalid = r.rentalid
      where  c.createdate BETWEEN TO_DATE('01-05-2019','dd-MM-yyyy') AND 
             TO_DATE('01-06-2019','dd-MM-yyyy') or
             (select round(sum(pp.amount))
                from PARTITIONED_payment_amount pp
                INNER join PARTITIONED_rental rr
                  on rr.rentalid = pp.rentalid
                where rr.customerid=c.customerid) < 50 
      group by c.firstname, c.lastname,c.createdate
      order by c.firstname, c.lastname
    

    另外 - 您在此查询中有 ANDOR 条件,它们没有被完全括起来。 ANDOR 的评估顺序可能不是你想象的那样。你是说

             (c.createdate BETWEEN TO_DATE('01-05-2019','dd-MM-yyyy') AND 
              TO_DATE('01-06-2019','dd-MM-yyyy')) or
             (select round(sum(pp.amount))
                from PARTITIONED_payment_amount pp
                INNER join PARTITIONED_rental rr
                  on rr.rentalid = pp.rentalid
                where rr.customerid=c.customerid) < 50
    

    或者你的意思是

             c.createdate BETWEEN TO_DATE('01-05-2019','dd-MM-yyyy') AND 
             (TO_DATE('01-06-2019','dd-MM-yyyy') or
              (select round(sum(pp.amount))
                 from PARTITIONED_payment_amount pp
                 INNER join PARTITIONED_rental rr
                   on rr.rentalid = pp.rentalid
                 where rr.customerid=c.customerid) < 50)
    

    如果您像这样混合使用 ANDOR,最好使用括号将操作分组为您想要的,否则您可能无法获得预期的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多