order by的使用及讲解

1. order by的使用

大家都清楚在hive中order by是用来排序的,使用语法如下

SELECT * FROM tab_name ORDER BY column_name;

在使用order by的时候默认是按照升序进行排序的(ASC),字符串类型就是按照字典顺序进行排序的,数值类型就是按照数值的大小进行排序的具体列子如下:
表中数据:

goods

gtype

price

口香糖

食品

10

薯片

食品

20

巧克力

食品

30

蛋糕

食品

40

薯条

食品

50

饼干

食品

60

面包

食品

70

月饼

食品

80

方便面

食品

90

洗衣粉

日用品

11

洗衣液

日用品

21

洗洁精

日用品

31

拖布

日用品

41

毛巾

日用品

51

卫生纸

日用品

61

水杯

日用品

71

水壶

日用品

81

椅子

日用品

91

电视

电器

12

电脑

电器

22

冰箱

电器

32

冰柜

电器

42

洗衣机

电器

52

小太阳

电器

62

电暖器

电器

72

电磁炉

电器

82

空调

电器

92

热水器

电器

102

表中字段price是int类型,其余都是string类型的
使用如下sql进行查询

select * from t_test order by price desc;

查询结果:

goods

gtype

price

热水器

电器

102

空调

电器

92

椅子

日用品

91

方便面

食品

90

电磁炉

电器

82

水壶

日用品

81

月饼

食品

80

电暖器

电器

72

水杯

日用品

71

面包

食品

70

小太阳

电器

62

卫生纸

日用品

61

饼干

食品

60

洗衣机

电器

52

毛巾

日用品

51

薯条

食品

50

冰柜

电器

42

拖布

日用品

41

蛋糕

食品

40

冰箱

电器

32

洗洁精

日用品

31

巧克力

食品

30

电脑

电器

22

洗衣液

日用品

21

薯片

食品

20

电视

电器

12

洗衣粉

日用品

11

口香糖

食品

10

这里我使用的倒序(desc)进行排序的,可以看到表中数据是以字段price进行倒序排序的,通常我们使用order by的时候都是但字段进行排序的,但是有的时候也会使用到多字段进行排序,在使用多字段排序的时候,我们需要在order by后的每个字段后面都注明排序方式,具体语法如下

SELECT * FROM tab_name ORDER BY column_1 desc,column_2,desc,column_3....

需要进行倒序排序的时候要在字段后面添加desc,不添加默认是asc排序,多字段的排序规则是先将第一个出现的字段按照正序或者倒序进行排序,在排序好之后,在第一个字段值相同的情况下第二个字段在以正序 或者倒序的方式的进行排序,可以理解位以第一个字段值做分组再以第二个字段进行排序,查询sql如下

select
 goods,
 case gtype
 when '食品'
 then concat("7_",gtype)
 when '日用品'
 then concat("3_",gtype)
 when '电器'
 then concat("5_",gtype)
 end gtype
 ,
 price
from t_test
order by gtype,price desc;

结果如下:

goods

gtype

price

椅子

3_日用品

91

水壶

3_日用品

81

水杯

3_日用品

71

卫生纸

3_日用品

61

毛巾

3_日用品

51

拖布

3_日用品

41

洗洁精

3_日用品

31

洗衣液

3_日用品

21

洗衣粉

3_日用品

11

热水器

5_电器

102

空调

5_电器

92

电磁炉

5_电器

82

电暖器

5_电器

72

小太阳

5_电器

62

洗衣机

5_电器

52

冰柜

5_电器

42

冰箱

5_电器

32

电脑

5_电器

22

电视

5_电器

12

方便面

7_食品

90

月饼

7_食品

80

面包

7_食品

70

饼干

7_食品

60

薯条

7_食品

50

蛋糕

7_食品

40

巧克力

7_食品

30

薯片

7_食品

20

口香糖

7_食品

10

因为gtype数据值都是汉字的,用来排序效果不容易看出来,所以都加了数字前缀,从结果可以看出来gtype是按照字典顺序的正序排序的,price字段是按照数值类型进行倒序排序的,通过这个例子就可以很直观看出来order by的排序规则。

2. order by在hive中的执行机制

order by是进行全局的排序,所以最终数据都会集中在一个reduce中,因为如果分散在多个reduce中就无法保证是全局排序,并且在hive使用order by的时候会受到如下属性的约束:

set hive.mapred.mode=nonstrict;
set hive.mapred.mode=strict;

默认是在nonstrict模式下的,如果在strict模式下使用order by的话必须使用limit关键字,因为如果数据量过大的话,执行的时间会非常长。
通过如下列子看一下:
首先设置位strict模式

set hive.mapred.mode=strict;

然后执行如下sql

select * from t_test order by price;

结果如下

FAILED: SemanticException 1:30 Order by-s without limit are disabled for safety reasons. If you know what you are doing, 
please sethive.strict.checks.large.query to false and that hive.mapred.mode is not set to 'strict' to proceed. 
Note that if you may get errors or incorrect results if you make a mistake while using some of the unsafe features.. 
Error encountered near token 'price'
Error: Error while compiling statement: FAILED: SemanticException 1:30 Order by-s without limit are disabled for safety reasons. 
If you know what you are doing, please sethive.strict.checks.large.query to false and that hive.mapred.mode is not set to 'strict' to proceed. 
Note that if you may get errors or incorrect results if you make a mistake while using some of the unsafe features.. Error encountered near token 'price' (state=42000,code=40000)

第一行就出现了“Order by-s without limit”,可以看到设置为strict模式后,不加limit是无法执行order by语句的
加上limit关键字,sql如下

select * from t_test order by price limit 7;

结果如下:

goods

gtype

price

口香糖

食品

10

洗衣粉

日用品

11

电视

电器

12

薯片

食品

20

洗衣液

日用品

21

电脑

电器

22

巧克力

食品

30