partition_partition by - CSDN
  • SQL进阶——GROUP BY 和 PARTITION BY

    万次阅读 2018-07-07 11:37:31
    运行环境 win10 / oracle(DB11g) 一、rank() 、 dense_rank() 、row_number() -- 创表 create table teams_5 ( member varchar(6), team varchar(4), age SMALLINT ...insert into teams_5 values (...

    运行环境 win10 / oracle(DB11g)

    一、rank()dense_rank()row_number()

    -- 创表
    create table teams_5
    (
        member varchar(6),
        team   varchar(4),
        age   SMALLINT
    )
    ;
    
    insert into teams_5 values ('大木', 'A', 28);
    insert into teams_5 values ('一件', 'A', 19);
    insert into teams_5 values ('新特', 'A', 23);
    insert into teams_5 values ('山田', 'B', 40);
    insert into teams_5 values ('九本', 'C', 30);
    insert into teams_5 values ('乔天', 'D', 28);
    insert into teams_5 values ('野野宫', 'D', 28);
    insert into teams_5 values ('加藤', 'D', 24);
    insert into teams_5 values ('新城', 'D', 22);
    
    -- 排序
    select member, team, age,
           rank() over(partition by team order by age desc) rn,
           dense_rank() over(partition by team order by age desc) dense_rn,
           row_number() over(partition by team order by age desc) row_num 
      from teams_5
     order by team, rn
    ;
    

    结果:

    MEMBER TEAM        AGE         RN   DENSE_RN    ROW_NUM
    ------ ---- ---------- ---------- ---------- ----------
    大木   A            28          1          1          1
    新特   A            23          2          2          2
    一件   A            19          3          3          3
    山田   B            40          1          1          1
    九本   C            30          1          1          1
    乔天   D            28          1          1          1
    野野宫 D            28          1          1          2
    加藤   D            24          3          2          3
    新城   D            22          4          3          4

    rn 位次有跳动,row_num连续

    二、用求余数分组 (抽样)

    -- 从原来的表中抽出(大约)五分之一的数据
    select *
      from sometbl
     where mod(seq, 5) = 0
    ;
    
    --如果没有连续编号,用row_number()函数生成
    select * 
      fromselect col,
                    row_number() over(order by col) as seq
              from somtbl)
     where mod(seq, 5) = 0
     ;

    内容多来自 《SQL进阶教材》,仅做笔记。

    展开全文
  • 深入解析MySQL分区(Partition)功能

    万次阅读 多人点赞 2017-08-25 10:53:40
    自5.1开始对分区(Partition)有支持,6.0应比较稳定 = 水平分区(根据列属性按行分)= 举个简单例子:一个包含十年发票记录的表可以被分区为十个不同的分区,每个分区包含的是其中一年的记录。 === 水平分区的几种...

    欢迎扫码加入Java高知群交流


    自5.1开始对分区(Partition)有支持

    = 水平分区(根据列属性按行分)=
    举个简单例子:一个包含十年发票记录的表可以被分区为十个不同的分区,每个分区包含的是其中一年的记录。

    === 水平分区的几种模式:===
    * Range(范围) – 这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区,80年代(1980's)的数据,90年代(1990's)的数据以及任何在2000年(包括2000年)后的数据。 

    * Hash(哈希) – 这中模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,。例如DBA可以建立一个对表主键进行分区的表。 

    * Key(键值) – 上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。 

    * List(预定义列表) – 这种模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如:DBA建立了一个横跨三个分区的表,分别根据2004年2005年和2006年值所对应的数据。 

    * Composite(复合模式) - 很神秘吧,哈哈,其实是以上模式的组合使用而已,就不解释了。举例:在初始化已经进行了Range范围分区的表上,我们可以对其中一个分区再进行hash哈希分区。 

    = 垂直分区(按列分)=
    举个简单例子:一个包含了大text和BLOB列的表,这些text和BLOB列又不经常被访问,这时候就要把这些不经常使用的text和BLOB了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。


    [分区表和未分区表试验过程]

    *创建分区表,按日期的年份拆分
    mysql> CREATE TABLE part_tab ( c1 int default NULL, c2 varchar(30) default NULL, c3 date default NULL) engine=myisam 
    PARTITION BY RANGE (year(c3)) (PARTITION p0 VALUES LESS THAN (1995),
    PARTITION p1 VALUES LESS THAN (1996) , PARTITION p2 VALUES LESS THAN (1997) ,
    PARTITION p3 VALUES LESS THAN (1998) , PARTITION p4 VALUES LESS THAN (1999) ,
    PARTITION p5 VALUES LESS THAN (2000) , PARTITION p6 VALUES LESS THAN (2001) ,
    PARTITION p7 VALUES LESS THAN (2002) , PARTITION p8 VALUES LESS THAN (2003) ,
    PARTITION p9 VALUES LESS THAN (2004) , PARTITION p10 VALUES LESS THAN (2010),
    PARTITION p11 VALUES LESS THAN MAXVALUE ); 
    注意最后一行,考虑到可能的最大值

    *创建未分区表
    mysql> create table no_part_tab (c1 int(11) default NULL,c2 varchar(30) default NULL,c3 date default NULL) engine=myisam;

    *通过存储过程灌入800万条测试数据

    mysql> set sql_mode=''; /* 如果创建存储过程失败,则先需设置此变量, bug? */

    mysql> delimiter //   /* 设定语句终结符为 //,因存储过程语句用;结束 */


    mysql> CREATE PROCEDURE load_part_tab()
           begin
        declare v int default 0;
        while v < 8000000
        do
            insert into part_tab
            values (v,'testing partitions',adddate('1995-01-01',(rand(v)*36520) mod 3652));
             set v = v + 1;
        end while;
        end
        //
    mysql> delimiter ;
    mysql> call load_part_tab();
    Query OK, 1 row affected (8 min 17.75 sec)
    mysql> insert into no_part_tab select * from part_tab;
    Query OK, 8000000 rows affected (51.59 sec)
    Records: 8000000 Duplicates: 0 Warnings: 0

    * 测试SQL性能

    mysql> select count(*) from part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31';

    +----------+
    | count(*) |
    +----------+
    |   795181 |
    +----------+

    1 row in set (0.55 sec)


    mysql> select count(*) from no_part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31'; 
    +----------+
    | count(*) |
    +----------+
    |   795181 |
    +----------+
    1 row in set (4.69 sec)
    结果表明分区表比未分区表的执行时间少90%。

    * 通过explain语句来分析执行情况
    mysql > explain select count(*) from no_part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31'\G
    /* 结尾的\G使得mysql的输出改为列模式 */                    
    *************************** 1. row ***************************
               id: 1
    select_type: SIMPLE
            table: no_part_tab
             type: ALL
    possible_keys: NULL
              key: NULL
          key_len: NULL
              ref: NULL
             rows: 8000000
            Extra: Using where
    1 row in set (0.00 sec)


    mysql> explain select count(*) from part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31'\G 

    *************************** 1. row ***************************
               id: 1
    select_type: SIMPLE
            table: part_tab
             type: ALL
    possible_keys: NULL
              key: NULL
          key_len: NULL
              ref: NULL
             rows: 798458
            Extra: Using where
    1 row in set (0.00 sec)
    explain语句显示了SQL查询要处理的记录数目

    * 试验创建索引后情况
    mysql> create index idx_of_c3 on no_part_tab (c3);
    Query OK, 8000000 rows affected (1 min 18.08 sec)
    Records: 8000000 Duplicates: 0 Warnings: 0

    mysql> create index idx_of_c3 on part_tab (c3);
    Query OK, 8000000 rows affected (1 min 19.19 sec)
    Records: 8000000 Duplicates: 0 Warnings: 0
    创建索引后的数据库文件大小列表:
    2008-05-24 09:23             8,608 no_part_tab.frm
    2008-05-24 09:24       255,999,996 no_part_tab.MYD
    2008-05-24 09:24        81,611,776 no_part_tab.MYI
    2008-05-24 09:25                 0 part_tab#P#p0.MYD
    2008-05-24 09:26             1,024 part_tab#P#p0.MYI
    2008-05-24 09:26        25,550,656 part_tab#P#p1.MYD
    2008-05-24 09:26         8,148,992 part_tab#P#p1.MYI
    2008-05-24 09:26        25,620,192 part_tab#P#p10.MYD
    2008-05-24 09:26         8,170,496 part_tab#P#p10.MYI
    2008-05-24 09:25                 0 part_tab#P#p11.MYD
    2008-05-24 09:26             1,024 part_tab#P#p11.MYI
    2008-05-24 09:26        25,656,512 part_tab#P#p2.MYD
    2008-05-24 09:26         8,181,760 part_tab#P#p2.MYI
    2008-05-24 09:26        25,586,880 part_tab#P#p3.MYD
    2008-05-24 09:26         8,160,256 part_tab#P#p3.MYI
    2008-05-24 09:26        25,585,696 part_tab#P#p4.MYD
    2008-05-24 09:26         8,159,232 part_tab#P#p4.MYI
    2008-05-24 09:26        25,585,216 part_tab#P#p5.MYD
    2008-05-24 09:26         8,159,232 part_tab#P#p5.MYI
    2008-05-24 09:26        25,655,740 part_tab#P#p6.MYD
    2008-05-24 09:26         8,181,760 part_tab#P#p6.MYI
    2008-05-24 09:26        25,586,528 part_tab#P#p7.MYD
    2008-05-24 09:26         8,160,256 part_tab#P#p7.MYI
    2008-05-24 09:26        25,586,752 part_tab#P#p8.MYD
    2008-05-24 09:26         8,160,256 part_tab#P#p8.MYI
    2008-05-24 09:26        25,585,824 part_tab#P#p9.MYD
    2008-05-24 09:26         8,159,232 part_tab#P#p9.MYI
    2008-05-24 09:25             8,608 part_tab.frm
    2008-05-24 09:25                68 part_tab.par

    * 再次测试SQL性能

    mysql> select count(*) from no_part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31'; 

    +----------+
    | count(*) |
    +----------+
    |   795181 |
    +----------+

    1 row in set (2.42 sec)   /* 为原来4.69 sec 的51%*/   


    重启mysql ( net stop mysql, net start mysql)后,查询时间降为0.89 sec,几乎与分区表相同。

    mysql> select count(*) from part_tab where c3 > date '1995-01-01' and c3 < date '1995-12-31'; 
    +----------+
    | count(*) |
    +----------+
    |   795181 |
    +----------+
    1 row in set (0.86 sec)

    * 更进一步的试验
    ** 增加日期范围
    mysql> select count(*) from no_part_tab where c3 > date '1995-01-01' and c3 < date '1997-12-31';
    +----------+
    | count(*) |
    +----------+
    | 2396524 |
    +----------+
    1 row in set (5.42 sec)

    mysql> select count(*) from part_tab where c3 > date '1995-01-01' and c3 < date '1997-12-31';
    +----------+
    | count(*) |
    +----------+
    | 2396524 |
    +----------+

    1 row in set (2.63 sec)


    ** 增加未索引字段查询
    mysql> select count(*) from part_tab where c3 > date '1995-01-01' and c3 < date
    '1996-12-31' and c2='hello';
    +----------+
    | count(*) |
    +----------+
    |        0 |
    +----------+
    1 row in set (0.75 sec)

    mysql> select count(*) from no_part_tab where c3 > date '1995-01-01' and c3 < date '1996-12-31' and c2='hello';
    +----------+
    | count(*) |
    +----------+
    |        0 |
    +----------+
    1 row in set (11.52 sec)


    = 初步结论 =
    * 分区和未分区占用文件空间大致相同 (数据和索引文件)
    * 如果查询语句中有未建立索引字段,分区时间远远优于未分区时间
    * 如果查询语句中字段建立了索引,分区和未分区的差别缩小,分区略优于未分区。


    = 最终结论 =
    * 对于大数据量,建议使用分区功能。
    * 去除不必要的字段
    * 根据手册, 增加myisam_max_sort_file_size 会增加分区性能

    [分区命令详解]

    = 分区例子 = 
    * RANGE 类型
    CREATE TABLE users (
           uid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
           name VARCHAR(30) NOT NULL DEFAULT '',
           email VARCHAR(30) NOT NULL DEFAULT ''
    )
    PARTITION BY RANGE (uid) (
           PARTITION p0 VALUES LESS THAN (3000000)
           DATA DIRECTORY = '/data0/data'
           INDEX DIRECTORY = '/data1/idx',
    
           PARTITION p1 VALUES LESS THAN (6000000)
           DATA DIRECTORY = '/data2/data'
           INDEX DIRECTORY = '/data3/idx',
    
           PARTITION p2 VALUES LESS THAN (9000000)
           DATA DIRECTORY = '/data4/data'
           INDEX DIRECTORY = '/data5/idx',
    
           PARTITION p3 VALUES LESS THAN MAXVALUE     DATA DIRECTORY = '/data6/data' 
           INDEX DIRECTORY = '/data7/idx'
    );
    在这里,将用户表分成4个分区,以每300万条记录为界限,每个分区都有自己独立的数据、索引文件的存放目录,与此同时,这些目录所在的物理磁盘分区可能也都是完全独立的,可以提高磁盘IO吞吐量。
          
    * LIST 类型
    CREATE TABLE category (
         cid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
         name VARCHAR(30) NOT NULL DEFAULT ''
    )
    PARTITION BY LIST (cid) (
         PARTITION p0 VALUES IN (0,4,8,12)
         DATA DIRECTORY = '/data0/data' 
         INDEX DIRECTORY = '/data1/idx',
         
         PARTITION p1 VALUES IN (1,5,9,13)
         DATA DIRECTORY = '/data2/data'
         INDEX DIRECTORY = '/data3/idx',
         
         PARTITION p2 VALUES IN (2,6,10,14)
         DATA DIRECTORY = '/data4/data'
         INDEX DIRECTORY = '/data5/idx',
         
         PARTITION p3 VALUES IN (3,7,11,15)
         DATA DIRECTORY = '/data6/data'
         INDEX DIRECTORY = '/data7/idx'
    );   
    分成4个区,数据文件和索引文件单独存放。

    * HASH 类型     
    CREATE TABLE users (
         uid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
         name VARCHAR(30) NOT NULL DEFAULT '',
         email VARCHAR(30) NOT NULL DEFAULT ''
    )
    PARTITION BY HASH (uid) PARTITIONS 4 (
         PARTITION p0
         DATA DIRECTORY = '/data0/data'
         INDEX DIRECTORY = '/data1/idx',
    
         PARTITION p1
         DATA DIRECTORY = '/data2/data'
         INDEX DIRECTORY = '/data3/idx',
    
         PARTITION p2
         DATA DIRECTORY = '/data4/data'
         INDEX DIRECTORY = '/data5/idx',
    
         PARTITION p3
         DATA DIRECTORY = '/data6/data'
         INDEX DIRECTORY = '/data7/idx'
    );
    分成4个区,数据文件和索引文件单独存放。

    例子:
    CREATE TABLE ti2 (id INT, amount DECIMAL(7,2), tr_date DATE)
        ENGINE=myisam
        PARTITION BY HASH( MONTH(tr_date) )
        PARTITIONS 6;
    
    CREATE PROCEDURE load_ti2()
           begin
        declare v int default 0;
        while v < 80000
        do
            insert into ti2
            values (v,'3.14',adddate('1995-01-01',(rand(v)*3652) mod 365));
             set v = v + 1;
        end while;
        end
        //


    * KEY 类型
    CREATE TABLE users (
         uid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
         name VARCHAR(30) NOT NULL DEFAULT '',
         email VARCHAR(30) NOT NULL DEFAULT ''
    )
    PARTITION BY KEY (uid) PARTITIONS 4 (
         PARTITION p0
         DATA DIRECTORY = '/data0/data'
         INDEX DIRECTORY = '/data1/idx',
         
         PARTITION p1
         DATA DIRECTORY = '/data2/data' 
         INDEX DIRECTORY = '/data3/idx',
         
         PARTITION p2 
         DATA DIRECTORY = '/data4/data'
         INDEX DIRECTORY = '/data5/idx',
         
         PARTITION p3 
         DATA DIRECTORY = '/data6/data'
         INDEX DIRECTORY = '/data7/idx'
    );   
    分成4个区,数据文件和索引文件单独存放。

    * 子分区
    子分区是针对 RANGE/LIST 类型的分区表中每个分区的再次分割。再次分割可以是 HASH/KEY 等类型。例如:
    CREATE TABLE users (
         uid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
         name VARCHAR(30) NOT NULL DEFAULT '',
         email VARCHAR(30) NOT NULL DEFAULT ''
    )
    PARTITION BY RANGE (uid) SUBPARTITION BY HASH (uid % 4) SUBPARTITIONS 2(
         PARTITION p0 VALUES LESS THAN (3000000)
         DATA DIRECTORY = '/data0/data'
         INDEX DIRECTORY = '/data1/idx',
    
         PARTITION p1 VALUES LESS THAN (6000000)
         DATA DIRECTORY = '/data2/data'
         INDEX DIRECTORY = '/data3/idx'
    );
    对 RANGE 分区再次进行子分区划分,子分区采用 HASH 类型。
    或者
    CREATE TABLE users (
         uid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
         name VARCHAR(30) NOT NULL DEFAULT '',
         email VARCHAR(30) NOT NULL DEFAULT ''
    )
    PARTITION BY RANGE (uid) SUBPARTITION BY KEY(uid) SUBPARTITIONS 2(
         PARTITION p0 VALUES LESS THAN (3000000)
         DATA DIRECTORY = '/data0/data'
         INDEX DIRECTORY = '/data1/idx',
    
         PARTITION p1 VALUES LESS THAN (6000000)
         DATA DIRECTORY = '/data2/data'
         INDEX DIRECTORY = '/data3/idx'
    );
    对 RANGE 分区再次进行子分区划分,子分区采用 KEY 类型。

    = 分区管理 =

        * 删除分区  
    ALERT TABLE users DROP PARTITION p0;

          删除分区 p0。


        * 重建分区
              o RANGE 分区重建
    ALTER TABLE users REORGANIZE PARTITION p0,p1 INTO (PARTITION p0 VALUES LESS THAN (6000000));
                将原来的 p0,p1 分区合并起来,放到新的 p0 分区中。
              o LIST 分区重建
    ALTER TABLE users REORGANIZE PARTITION p0,p1 INTO (PARTITION p0 VALUES IN(0,1,4,5,8,9,12,13));
                将原来的 p0,p1 分区合并起来,放到新的 p0 分区中。
              o HASH/KEY 分区重建
     ALTER TABLE users REORGANIZE PARTITION COALESCE PARTITION 2;
                用 REORGANIZE 方式重建分区的数量变成2,在这里数量只能减少不能增加。想要增加可以用 ADD PARTITION 方法。
        * 新增分区
              o 新增 RANGE 分区   
     ALTER TABLE category ADD PARTITION (PARTITION p4 VALUES IN (16,17,18,19)
                DATA DIRECTORY = '/data8/data'
                INDEX DIRECTORY = '/data9/idx');
                新增一个RANGE分区。
              o 新增 HASH/KEY 分区
      ALTER TABLE users ADD PARTITION PARTITIONS 8;
                将分区总数扩展到8个。

    [ 给已有的表加上分区 ]
    alter table results partition by RANGE (month(ttime)) 
    (PARTITION p0 VALUES LESS THAN (1),
    PARTITION p1 VALUES LESS THAN (2) , PARTITION p2 VALUES LESS THAN (3) ,
    PARTITION p3 VALUES LESS THAN (4) , PARTITION p4 VALUES LESS THAN (5) ,
    PARTITION p5 VALUES LESS THAN (6) , PARTITION p6 VALUES LESS THAN (7) ,
    PARTITION p7 VALUES LESS THAN (8) , PARTITION p8 VALUES LESS THAN (9) ,
    PARTITION p9 VALUES LESS THAN (10) , PARTITION p10 VALUES LESS THAN (11),
    PARTITION p11 VALUES LESS THAN (12),
    PARTITION P12 VALUES LESS THAN (13) ); 


    默认分区限制分区字段必须是主键(PRIMARY KEY)的一部分,为了去除此
    限制:
    [方法1] 使用ID
    mysql> ALTER TABLE np_pk
        ->     PARTITION BY HASH( TO_DAYS(added) )
        ->     PARTITIONS 4;
    ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

    However, this statement using the id column for the partitioning column is valid, as shown here:

    mysql> ALTER TABLE np_pk
        ->     PARTITION BY HASH(id)
        ->     PARTITIONS 4;
    Query OK, 0 rows affected (0.11 sec)
    Records: 0 Duplicates: 0 Warnings: 0

    [方法2] 将原有PK去掉生成新PK
    mysql> alter table results drop PRIMARY KEY;
    Query OK, 5374850 rows affected (7 min 4.05 sec)
    Records: 5374850 Duplicates: 0 Warnings: 0

    mysql> alter table results add PRIMARY KEY(id, ttime);
    Query OK, 5374850 rows affected (6 min 14.86 sec)

    Records: 5374850 Duplicates: 0 Warnings: 0


    欢迎加入java讨论群:130188005

    欢迎扫码加入Java高知群交流


    展开全文
  • partition

    2016-10-12 14:00:23
    出处:... STL 中的划分算法 partition 的函数原型如下 [cpp] view plain copy print? template class ForwardIterator, class Predicate> ForwardItera

    出处:http://blog.csdn.net/justme0/article/details/24496767


    STL 中的划分算法 partition 的函数原型如下

    1. template <class ForwardIterator, class Predicate>  
    2. ForwardIterator partition(ForwardIterator first, ForwardIterator last, Predicate pred);  
    四点说明:

    1、功能:将 [first, last) 中所有满足 pred 的元素置于不满足 pred 的元素前面。

    2、返回值:设返回的迭代器为 i,则对 [first, i) 中的任意迭代器 j,pred(*j) 为真,对 [i, last) 中的任意迭代器 k,pred(*k) 为假。

    3、要求:ForwardIterator 必须满足 ValueSwappable。

    4、复杂度:如果 ForwardIterator 符合 BidirectionalIterator 的要求,则最多进行 (last - first) / 2 次交换;否则最多 last - first 次交换。且执行 last - first 次的 pred 操作。

    源码如下:

    1. /******************************************************************** 
    2. created:    2014/04/25 15:37 
    3. filename:   partition.cpp 
    4. author:     Justme0 (http://blog.csdn.net/justme0) 
    5.  
    6. purpose:    partition 
    7. *********************************************************************/  
    8.   
    9. #include <cstdio>  
    10. #include <cstdlib>  
    11.   
    12. typedef int T;  
    13.   
    14. template <class ForwardIterator1, class ForwardIterator2>  
    15. inline void iter_swap(ForwardIterator1 a, ForwardIterator2 b) {  
    16.     T tmp = *a;     // 源码中的 T 由迭代器的 traits 得来,这里简化了  
    17.     *a = *b;  
    18.     *b = tmp;  
    19. }  
    20.   
    21. template <class Type>  
    22. inline void swap(Type &a, Type &b) {  
    23.     Type tmp = a;  
    24.     a = b;  
    25.     b = tmp;  
    26. }  
    27.   
    28. /* 
    29. ** 设返回值为 mid,则[first, mid)中迭代器指向的值满足 pred; 
    30. ** [mid, last)中迭代器指向的值不满足 pred 
    31. ** 为双向迭代器设计的算法 
    32. ** 迭代器用到了自减操作 
    33. */  
    34. template <class BidirectionalIterator, class Predicate>  
    35. BidirectionalIterator partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred) {  
    36.     while(true) {  
    37.         while(true) {  
    38.             if (first == last) {  
    39.                 return first;  
    40.             } else if (pred(*first)) {  
    41.                 ++first;  
    42.             } else {  
    43.                 break;  
    44.             }  
    45.         }  
    46.         --last;  
    47.         while(true) {  
    48.             if (first == last) {  
    49.                 return first;  
    50.             } else if (!pred(*last)) {  
    51.                 --last;  
    52.             } else {  
    53.                 break;  
    54.             }  
    55.         }  
    56.         iter_swap(first, last);  
    57.         ++first;  
    58.     }  
    59. }  
    60.   
    61. /* 
    62. ** 为前向迭代器设计的算法 
    63. ** 这里为了不与为双向迭代器设计的 partition 同名,加了后缀以区别 
    64. ** 源码中由 traits 得到不同类型的迭代器标记形成重载 
    65. */  
    66. template <class ForwardIterator, class Predicate>  
    67. ForwardIterator partition2(ForwardIterator first, ForwardIterator last, Predicate pred) {  
    68.     if (first == last) {  
    69.         return first;  
    70.     }  
    71.   
    72.     while (pred(*first)) {  
    73.         if (++first == last) {  
    74.             return first;  
    75.         }  
    76.     }  
    77.     ForwardIterator next = first;  
    78.     while (++next != last) {  
    79.         if (pred(*next)) {  
    80.             swap(*first, *next);  
    81.             ++first;  
    82.         }  
    83.     }  
    84.   
    85.     return first;  
    86. }  
    87.   
    88. /* 
    89. ** 设返回值为 mid,则[first, mid)中迭代器指向的值小于等于 pivot; 
    90. ** [mid, last)中迭代器指向的值大于等于 pivot 
    91. ** 这是 STL 内置的算法,会用于 nth_element, sort 中 
    92. ** 笔者很困惑为什么不用 partition 
    93. */  
    94. template <class RandomAccessIterator, class Type>  
    95. RandomAccessIterator unguarded_partition(RandomAccessIterator first, RandomAccessIterator last, Type pivot) {  
    96.     while(true) {  
    97.         while (*first < pivot) {  
    98.             ++first;  
    99.         }  
    100.         --last;  
    101.         while (pivot < *last) {  // 若 std::partition 的 pred 是 IsLess(pivot),这里将是小于等于  
    102.             --last;  
    103.         }  
    104.         if (!(first < last)) {   // 小于操作只适用于 random access iterator  
    105.             return first;  
    106.         }  
    107.         iter_swap(first, last);  
    108.         ++first;  
    109.     }  
    110. }  
    111.   
    112. template <class Type>  
    113. struct IsLess {  
    114.     IsLess(const Type &pivot) : m_pivot(pivot) {}  
    115.   
    116.     bool operator()(const Type &other) const {  
    117.         return other < m_pivot;  
    118.     }  
    119.   
    120. private:  
    121.     Type m_pivot;  
    122. };  
    123.   
    124. void print(int *array, int len) {  
    125.     for (int i = 0; i < len; ++i) {  
    126.         printf("%d ", array[i]);  
    127.     }  
    128.     printf("\n");  
    129. }  
    130.   
    131. int main(void) {  
    132.     {  
    133.         int arr[] = {2, 30, 30, 17, 33, 40, 17, 23, 22, 12, 20};  
    134.         int size = sizeof arr / sizeof *arr;  
    135.   
    136.         int *mid = partition(arr, arr + size, IsLess<int>(22));  
    137.         print(arr, size);                                       // 2 20 12 17 17 40 33 23 22 30 30  
    138.         printf("partition return %d\n", mid - arr);             // partition return 5  
    139.     }  
    140.   
    141.     {  
    142.         int arr[] = {2, 30, 30, 17, 33, 40, 17, 23, 22, 12, 20};  
    143.         int size = sizeof arr / sizeof *arr;  
    144.   
    145.         int *mid = partition2(arr, arr + size, IsLess<int>(22));  
    146.         print(arr, size);                                       // 2 17 17 12 20 40 30 23 22 30 33  
    147.         printf("partition2 return %d\n", mid - arr);            // partition2 return 5  
    148.     }  
    149.   
    150.     {  
    151.         int arr[] = {2, 30, 30, 17, 33, 40, 17, 23, 22, 12, 20};  
    152.         int size = sizeof arr / sizeof *arr;  
    153.   
    154.         int *mid = unguarded_partition(arr, arr + size, 22);  
    155.         print(arr, size);                                       // 2 20 12 17 22 17 40 23 33 30 30  
    156.         printf("unguarded_partition return %d\n", mid - arr);   // unguarded_partition return 6  
    157.     }  
    158.   
    159.     system("PAUSE");  
    160.     return 0;  
    161. }  
    如果大家对程序有任何疑问可以在下面回复,因为当中省略了很多 STL 的设计技巧以突出算法。
    展开全文
  • 分区函数Partition By的用法

    万次阅读 2019-03-25 16:31:12
    group by是分组函数,partition by是分区函数(像sum()等是聚合函数),注意区分。 1、over函数的写法: over(partition by class order by sroce) 先对class中相同的进行分区,在class中相同的情况下对sroce...

    group by是分组函数,partition by是分区函数(像sum()等是聚合函数),注意区分。

    1、over函数的写法:

    over(partition by cno order by degree )
    

    先对cno 中相同的进行分区,在cno 中相同的情况下对degree 进行排序

    2、分区函数Partition By与rank()的用法“对比”分区函数Partition By与row_number()的用法

    例:查询每名课程的第一名的成绩

    (1)使用rank()
    SELECT	* 
    FROM	(select sno,cno,degree,
          	rank()over(partition by cno order by degree desc) mm 
          	from score) 
    where mm = 1;
    

    得到结果:
    在这里插入图片描述

    (2)使用row_number()
    SELECT * 
    FROM   (select sno,cno,degree,
           row_number()over(partition by cno order by degree desc) mm 
           from score) 
    where mm = 1;
    

    得到结果:
    在这里插入图片描述

    (3)rank()与row_number()的区别

    由以上的例子得出,在求第一名成绩的时候,不能用row_number(),因为如果同班有两个并列第一,row_number()只返回一个结果。

    2、分区函数Partition By与rank()的用法“对比”分区函数Partition By与dense_rank()的用法

    例:查询课程号为‘3-245’的成绩与排名

    (1) 使用rank()
    SELECT * 
    FROM   (select sno,cno,degree,
           rank()over(partition by cno order by degree desc) mm 
           from score) 
    where cno = '3-245'
    

    得到结果:
    在这里插入图片描述

    (2) 使用dense_rank()
    SELECT * 
    FROM   (select sno,cno,degree,
           dense_rank()over(partition by cno order by degree desc) mm 
           from score) 
    where cno = '3-245'
    

    得到结果:
    在这里插入图片描述

    (3)rank()与dense_rank()的区别

    由以上的例子得出,rank()和dense_rank()都可以将并列第一名的都查找出来;但rank()是跳跃排序,有两个第一名时接下来是第三名;而dense_rank()是非跳跃排序,有两个第一名时接下来是第二名。

    展开全文
  • Partition函数

    万次阅读 2017-08-17 15:06:27
    快排中核心的方法应该算是Partition函数了,它的作用就是将整个数组分成小于基准值的左边,和大于基准值的右边。普通的Partition函数是这样的:public static int partition1(int[] array,int lo,int hi){ //以第一...
  • C++ stl算法——partition

    千次阅读 2018-02-06 11:28:32
    ForwardIt partition( ForwardIt first, ForwardIt last, UnaryPredicate p );作用对[first, last)元素进行处理,使得满足p的元素移到[first, last)前部,不满足的移到后部,返回第一个不满足p元素所在的迭代
  • Partition方法

    千次阅读 2019-09-09 22:16:24
    * partition()方法:在基准元素左边的元素都小于基准元素,在基准元素右边的元素都大于等于基准元素。 * * 可以使用partition()方法解决以下常见的问题: * * 1)查找数组中出现次数超过数组长度一半的元素。 ...
  • Hive分区partition详解

    万次阅读 多人点赞 2017-11-03 11:30:34
    Hive分区partition详解
  • OVER(PARTITION BY)函数介绍

    万次阅读 2019-05-21 13:37:01
    问题场景   最近在项目中遇到了对每一个类型进行求和并且求该类型所占的比例,当时考虑求出每种类型的和,并在java中分别对每一种类型的和与总和相除求出所占比例。后来,想到这样有点麻烦,并且项目中持久层...
  • Window 解决开机报错:Invalid Partition Table

    万次阅读 热门讨论 2019-11-13 12:48:04
    Invalid Partition Table,即无效磁盘分区,硬盘不能启动。 一般我们都会使用多硬盘的Windows电脑,如固态硬盘+机械硬盘结合的双硬盘搭配。出现这个报错原因就是开机时默认启动加载机械硬盘了,可以简单理解为没有...
  • hive OVER(PARTITION BY)函数用法

    万次阅读 2016-11-23 21:19:50
    OVER(PARTITION BY)函数用法  2010年10月26日 OVER(PARTITION BY)函数介绍 开窗函数   Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组...
  • 【Orcale】分析函数 OVER(PARTITION BY... ORDER BY...)的讲解

    万次阅读 多人点赞 2019-03-20 09:58:26
    OVER(PARTITION BY... ORDER BY...)的使用说明和意义 这个函数长这个样子:OVER(PARTITION BY... ORDER BY...) 顾名思义,PARTITION 中文是分割的意思,ORDER 是排序的意思,所以翻译一下就是先把一组数据按照制定...
  • 最近HM给XSD一个需求,HM说现在我们的自动调度任务每天都运行了很多任务,而且每个任务又有...XSD以前写过HIVE脚本,记得有个 PARTITION BY语句 通过 ROW_NUMBER() over (PARTITION BY xx ORDER BY ** DESC) as row_
  • row_number() OVER(PARTITION BY)函数介绍

    万次阅读 2012-04-01 16:34:24
    OVER(PARTITION BY)函数介绍 开窗函数   Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行。 ...
  • partition.bin资料如图: ![图片说明](https://img-ask.csdn.net/upload/202005/10/1589118129_490875.png) 然后根据各位前辈的相关教程 制作黑砖救砖文件 partition.xml如现下(希望懂得指点下错误) ``` ...
  • Spark RDD之Partition

    万次阅读 多人点赞 2017-03-16 19:41:20
    概要Partition是Spark RDD一个重要组成,一份待处理的原始数据会被按照相应的逻辑(例如jdbc和hdfs的split逻辑)切分成n份,每份数据对应到RDD中的一个partitionPartition的数量决定了task的数量,影响着程序的并行...
  • 前言 ...如果在Oracle中可以通过分析函数 OVER(PARTITION BY… ORDER BY…)来实现。在MySQL中应该怎么来实现呢。现在通过两种简单的方式来实现这一需求。 数据准备 /*Table structure fo...
  • hadoop开发中我们会遇到类似这样的问题,比如 如何将不同省份的手机号分别输出到不同的文件中,本片文章将对hadoop内置的Partition类进行重写以解决这个问题。    MapReduce的使用者通常会指定Reduce任务和...
  • hive分区(partition)简介

    万次阅读 2014-07-15 21:37:57
    网上有篇关于hive的partition的使用讲解的比较好,转载了: 一、背景 1、在Hive Select查询中一般会扫描整个表内容,会消耗很多时间做没必要的工作。有时候只需要扫描表中关心的一部分数据,因此建表时引入了...
  • kafka的Consumer均衡算法有一个topic:lijietest,然后这个topic的partition和他们所在的broker的图如下:1.其中 broker有两个,也就是服务器有两台。2.partition有6个,分布按照如图所示,按照哈希取模的算法分配。...
1 2 3 4 5 ... 20
收藏数 291,873
精华内容 116,749
关键字:

partition