數(shù)據(jù)分析_HiveSQL查詢語句

Hive 數(shù)據(jù)類型

基本數(shù)據(jù)類型

數(shù)據(jù)類型 長度 例子
tinyint 1byte有符號整數(shù) 20
smallint 2byte有符號整數(shù) 20
int 4byte有符號整數(shù) 20
bigint 8byte有符號整數(shù) 20
boolean 布爾類型,true或者false TRUE
float 單精度浮點(diǎn)數(shù) 3.14159
double 雙精度浮點(diǎn)數(shù) 3.14159
string 字符序列??梢灾付ㄗ址???梢允褂脝我柣蛘唠p引號 ‘now is the time’,’for all good men’
timestamp 整數(shù),浮點(diǎn)數(shù)或者字符串 1327882394(UNIX新紀(jì)元秒),1327882394.123456789(UNIX新紀(jì)元秒并跟隨納秒數(shù))和’2016-03-13 16:23:30.123456789’(JDBC所兼容的java.sql.Timestamp時間格式)
binary 字節(jié)數(shù)組 請看后面的討論

注:Hive會隱式地將類型轉(zhuǎn)換為兩個整型類型中值較大的那個類型;

集合數(shù)據(jù)類型

數(shù)據(jù)類型 描述 字面語法示例
struct 如果某個列的數(shù)據(jù)定義是struct{first String, last String}
取數(shù)方式:struct.first
struct('John', 'Doe')
map 一組“鍵值對”元組集合
取數(shù)方式:map['first']
map('first', 'John','last' , 'Doe')
array 每個元素都有一個編號,編號從零開始
取數(shù)方式:array[0]
array('John', 'Doe')

示例(用類似JSON的結(jié)構(gòu)描述):

{
    "names": ["Smith" , "Jones"] ,   //列表Array, names[1]="Jones"
    "deductions": {                  //鍵值Map, deductions[’Federal’]=0.2
        "Federal": 0.2 ,
        "State": 0.05,
        "Insurance": 0.1
    }
    "address": {                     //結(jié)構(gòu)Struct, address.city=”Chicago”
        "street": "1 Michigan Ave." ,
        "city": "Chicago" ,
        "state": "IL" ,
        "zip": 60600
    }
}

在Hive中實(shí)際存儲形式:

Smith_Jones,Federal:0.2_State:0.05_Insurance:0.1,Michigan Ave._Chicago_1L_60600
Jan_Ketty,Federal:0.2_State Taxes:0.05_Insurance:0.1,Guang dong._China_0.5L_60661

注:MAP,STRUCT和ARRAY里的元素間關(guān)系都可以用同一個字符表示,這里用“_”

取數(shù):

select names[1], deductions['Federal'],address.city
from learn.employees;
------
OK
Jones     0.2    Chicago
Ketty    0.2    China
Time taken: 0.123 seconds, Fetched: 2 row(s)

文本文件數(shù)據(jù)編碼

Hive中默認(rèn)的記錄和字段分隔符

分隔符 名稱 說明
\n 換行符 對于文本文件而言,每一行是一條記錄,因此換行符可以分割數(shù)據(jù)。
^A <Ctrl>+A 常用于分隔列,在CREATE TABLE語句中可以使用八進(jìn)制編碼\001 表示。
^B <Ctrl>+B 常用于分隔ARRAY與STRUCT元素,或用于MAP中鍵值對之間的分隔。CREATE TABLE語句中可以使用八進(jìn)制編碼\002 表示
^C <Ctrl+C> MAP中鍵值對的分隔。CREATE TABLE語句中可以使用八進(jìn)制編碼\003 表示
\t 制表符 常用
, 逗號 常用

在創(chuàng)建表格的時候,可規(guī)定分隔符:

create table employee(
name            string,
salary          float,
subordinates    array<string>,
deductions      map<string, float>,
address         struct<street:string, city:string, state:string, zip:int>
)
row format delimited
fields terminated by '\001'    //列分隔符
collection items terminated by '\002'               //集合元素間的分隔符
map keys terminated by '\003'                      //map 鍵值對的分隔符
lines terminated by '\n'                        //行與行之間的分隔符,只支持'\n'
stored as textfile;        

讀時模式

Hive處理的數(shù)據(jù)是大數(shù)據(jù),在保存表數(shù)據(jù)時不對數(shù)據(jù)進(jìn)行校驗(yàn),而是在讀數(shù)據(jù)時校驗(yàn),不符合格式的數(shù)據(jù)設(shè)置為NULL;

讀時模式的優(yōu)點(diǎn)是,加載數(shù)據(jù)庫快。

HiveQL:數(shù)據(jù)定義

Hive不支持行級插入操作、更新操作和刪除操作,Hive也不支持事務(wù)。
HiveQL數(shù)據(jù)定義語言部分,用于創(chuàng)建、修改和刪除數(shù)據(jù)庫、表、試圖、函數(shù)和索引

Hive中的數(shù)據(jù)庫

創(chuàng)建數(shù)據(jù)庫:

create database financials;

防止因“已存在”而拋出錯誤:

create database if not exits financials;

查看包含的數(shù)據(jù)庫:

show databases;
---
default
financials

使用正則表達(dá)式匹配:

show databases like 'h.*';
---
human_resources

存儲位置:
Hive會為每個數(shù)據(jù)庫創(chuàng)建一個目錄。數(shù)據(jù)庫中的表將會以這個數(shù)據(jù)庫目錄子目錄的形式存儲。數(shù)據(jù)庫所在目錄位于屬性hive.metastore.warehouse.dir所指定的頂層目錄之后??赏ㄟ^如下命令修改:

hive> create database financials
    > location '/my/preferred/directory'

描述信息:

hive> create database financials
    > comment 'Holds all financial tables'

hive> describe database financials;
---
financials Holds all financial tables
  hdfs://master-server/user/hive/warehouse/financials.db

設(shè)置為當(dāng)前的工作數(shù)據(jù)庫

hive> use financials;

顯示正在使用的數(shù)據(jù)庫

hive> set hive.cli.print.current.db=true;

hive (financials)> use default;

hive (default)> set hive.cli.print.current.db=false;

hive> ...

刪除數(shù)據(jù)庫

hive> drop database if exists financials;  //if exists可選,避免拋出警告

注:默認(rèn)情況下,Hive是不允許用戶刪除一個包含有表的數(shù)據(jù)庫的;要么先刪表,再刪庫;要么加上關(guān)鍵字 cascade

hive> drop database if exists financials cascade;

修改數(shù)據(jù)庫
使用 alter database命令為某個數(shù)據(jù)庫的dbproperties設(shè)置鍵-值對屬性,來描述這個數(shù)據(jù)庫的屬性信息。其他信息不可更改。

hive> alter database financials set dbproperties ('edited-by' = 'Joe Dba')

創(chuàng)建表

在mydb庫中增加employees表:
create table if not exists mydb.employees(
    name              string                comment    'employee name'//comment 后面是屬性
    salary            float                 comment    'employee salary'
    subordinates      array<string>         comment  'names of subordinates'
    deductions        map<string, float>    comment   'names,values'
    address           struct<street:string, city:string, state:string, zip:int> comment 'home address'
)
comment  'description of the table'
tblproperties  ('creator'='me','created_at'='2012-01-02')//可通過鍵值對增加配置信息
location '/user/hive/warehouse/mydb.db/employees';

拷貝一張已經(jīng)存在的表的表模式(而無需拷貝數(shù)據(jù)):

create table if not exists mydb.employees2
like mydb.employees;

呈現(xiàn)所有表

use mydb;
show tables;
----
employees
employees2

呈現(xiàn)所有表,不在當(dāng)前數(shù)據(jù)庫情況下:

show tables in mydb;
----
employees
employees2

過濾所需表

show tables '*.ees2'
----
employees2

查看表結(jié)構(gòu)信息:

describe extended mydb.employees;
----
name string employee name
...

查看更詳細(xì)信息

describe formatted mydb.employees;
----
name string employee name
...

只查看某一列的信息

described mydb.employees.salary;
---
salary float employees salary
管理表vs外部表

上面創(chuàng)建的是所謂的管理表,也被稱為內(nèi)部表;刪除表的時候,會刪除數(shù)據(jù)。
現(xiàn)在可以創(chuàng)建外部表,其可以讀取所有位于/data/stocks 目錄下的以逗號分隔的數(shù)據(jù):

create external table if not exists stocks (
    exchange      string,
    symbol        string,
    ymd           string,
    price_open    float,
    price_high    float,
    price_low     float,
    price_close   float,
    volume        int,
    price_adj_close    float
)
row format delimited fields terminated by ','
location  '/data/stocks'

external告訴hive這個表是外部的,location告訴hive數(shù)據(jù)位于哪個路徑。這個表對相關(guān)文件無控制權(quán),因此刪除表并不會刪除數(shù)據(jù)。
通過describe extended tablename查看表信息的時候,可查看是管理表還是外部表:

...tableType:managed_table;
...tableType:external_table;

用戶還可以對一張存在的表進(jìn)行表結(jié)構(gòu)的復(fù)制(不復(fù)制數(shù)據(jù)),這里external關(guān)鍵詞決定了無論源表是管理表還是外部表,創(chuàng)建的表都是外部表。

create external table if not exists mydb.employees3
like mydb.employees
location '/path/to/data';

分區(qū)表、管理表

分區(qū)管理表具有明顯的性能優(yōu)勢
先按照country再按照state來對數(shù)據(jù)進(jìn)行分析:

create table if not exists mydb.employees(
    name              string                comment    'employee name'
    salary            float                 comment    'employee salary'
    subordinates      array<string>         comment  'names of subordinates'
    deductions        map<string, float>    comment   'names,values'
    address           struct<street:string, city:string, state:string, zip:int> comment 'home address'
)
partitioned by (country string,state string);

之前的表存儲在如下目錄:

hdfs://master_server/user/hive/warehouse/mydb.db/employees

數(shù)據(jù)是按照如下子目錄存儲的:

...
.../employees/country=CA/state=AB
.../employees/country=CA/state=BC
...
.../employees/country=US/state=AL
.../employees/country=US/state=AK
...

如何在分區(qū)表查找信息:

select *
from employees
where country = 'US' and state = 'AL'

設(shè)置“strice”模式,對分區(qū)表查詢的時候如果不對分區(qū)進(jìn)行過濾,則任務(wù)不會提交:

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

查看所有分區(qū)

show partitions employees;
-----
country=CA/state=AB
country=CA/state=BC
...
show partitions employees partition (country='US');
-----
country=US/state=AL
country=US/state=AK
...

如何引用HOME環(huán)境變量:

load data local inpath '${env:HOME}/california-employees'
into table employees
patition (country = 'US', state = 'CA');

Hive會把${env:HOME}/california-employees這個目錄下面的文件將會拷貝到上述分區(qū)目錄下。

外部分區(qū)表

外部表也可以使用分區(qū),可首先創(chuàng)建分區(qū),然后載入數(shù)據(jù)

create external table if not exists log_messages(
    hms           int,
    severity      string,
    server        string,
    process_id    int,
    message       string
)
partitoned by (year int, month int, day int)
row format delimited fields terminated by '\t';
//這里不要求location子句

可通過alter table語句可以單獨(dú)進(jìn)行增加分區(qū)(同樣適用于管理表)

alter table log_messages add partition(year=2012,month=1,day=2)
location 'hdfs://master_server/data/log_messages/2012/01/02';

刪除表

drop table if exists employees

管理表:刪除表的元信息和數(shù)據(jù)
外部表:刪除表的元信息

修改表

修改表只會影響表的元信息,用戶需自己確保數(shù)據(jù)符合元信息要求。

表重命名
alter table log_messages rename to logmsgs;
增加、修改、刪除表分區(qū)

增加

alter table log_messages add if not exists
partition (year=2012, month=1, day = 1) location '/logs/2011/01/01'
partition (year=2012, month=1, day = 2) location '/logs/2011/01/02'
...

修改

alter table log_messages partition (year=2012, month=1, day = 2) 
set location 's3n:/ourbucket/logs/2011/01/02'

刪除

alter table log_messages drop if exists partition (year=2012, month=1, day = 2) 
修改列信息
alter table log_messages
change columns hms hours_minutes_seconds int
comment 'the hours, minutes, and seconds part of the timestamp'
after severity;

重命名、改類型,改列順序到severity后面(如果想移動到第一個位置則要用first替代after severity
上述語句只修改元數(shù)據(jù),用戶需保證數(shù)據(jù)符合元數(shù)據(jù)的要求。

增加列
alter table log_messages add columns(
    app_name     string   comment 'application name',
    session_id   long     comment 'the current session id'
);
刪除或替換列(等于整表替換為如下的列)
alter table log_messages replace columns(
     hours_mins_secs int comment 'hour,minute,seconds from timestamp',
     severity string comment 'The message severity',
     message string comment 'The rest of the message'
)
修改表屬性
alter table log_messages set tblproperties (
    'notes' = 'the process id is no longer captured;this column is always NULL'
)

HiveQL:數(shù)據(jù)操作

向管理表中裝載數(shù)據(jù)

load data local inpath '${env:HOME}/california-employees' 
overwrite into table employees
patition (country='US', state='CA')

local 關(guān)鍵字說明指定的目錄是本地的,如果沒有l(wèi)ocal 關(guān)鍵字則應(yīng)該是分布式文件系統(tǒng)中的路徑。
overwrite 關(guān)鍵字說明先刪除原先存在的數(shù)據(jù),沒有這個關(guān)鍵字則不刪除。

通過查詢語句向表中插入數(shù)據(jù)
insert overwrite table employees
partition (country = 'US', state = 'OR')
select * from staged_employees se
where se.cnty = 'US' and se.st = 'OR'

如果需要多種對應(yīng)關(guān)系,無需寫很多遍上面的語句,按如下格式插入數(shù)據(jù)效率會高(只需要掃描一遍):

from staged_employees se
insert overwrite table employees
    partition (country = 'US', state = 'OR')
    select * where se.cnty = 'US' and se.st = 'OR'
insert overwrite table employees
    partition (country = 'US', state = 'CA')
    select * where se.cnty = 'US' and se.st = 'CA'
insert overwrite table employees
    partition (country = 'US', state = 'IL')
    select * where se.cnty = 'US' and se.st = 'IL'
動態(tài)分區(qū)插入
insert overwrite table employees
partition (country, state)
select ...,se.cnty,se.st
from staged_employees se;

hive根據(jù)select語句中最后2列來確定分區(qū)字段country和state的值

混合使用動態(tài)和靜態(tài)分區(qū)
insert overwrite table employees
partition (country = 'US',state)
select  ...,se.cnty,se.st
from staged_employees se
where se.cnty = 'US'

country字段為靜態(tài),state是動態(tài)值,靜態(tài)分區(qū)鍵必須在動態(tài)分區(qū)鍵之前。
動態(tài)分區(qū)屬性

hive.exec.dynamic.partition 設(shè)置為true,表示開啟動態(tài)分區(qū)功能

單個查詢語句中創(chuàng)建表并加載數(shù)據(jù)

create table ca_employees
as select name, salary, address
from employees se
where se.state = 'CA'

創(chuàng)建表并載入數(shù)據(jù),不能用于外部表。

導(dǎo)出數(shù)據(jù)

將所有的字段序列化為字符串寫入到文件中

insert overwrite local directory '/tmp/ca_employees'
select name, salary, address
from employees
where state = 'CA';

輸入到多個文件

from staged_employees se
insert overwrite directory '/tmp/or_employees'
    select * where se.cty = 'US' and se.st = 'OR'
insert overwrite directory '/tmp/ca_employees'
    select * where se.cty = 'US' and se.st = 'CA'
insert overwrite directory '/tmp/il_employees'
    select * where se.cty = 'US' and se.st = 'IL'

視圖

Hive先執(zhí)行這個視圖,然后使用這個結(jié)果進(jìn)行余下后續(xù)的查詢

create view if not exists shipments(time, part)
comment 'time and parts for shipments。'
tblproperties ('creator' = 'me')
as
select ...;

if not existscomment是可選子句。

  • 復(fù)制視圖create view shipments2 like shipments;
  • 刪除視圖drop view if exists shipments
  • 顯示視圖清單show tables
  • 視圖不能作為insert語句和load命令的目標(biāo)表
  • 視圖是只讀的

HiveQL 查詢

select...from 語句

select e.name,e.salary
from employees e;

查詢集合數(shù)據(jù)

查詢數(shù)組

注:集合的字符串元素是加上引號的,而基本數(shù)據(jù)類型string的列值是不加引號的。

select name,subordinates
from employees;
---
John Doe        ["Mary Smith","Todd Jones"]
Mary Smith      ["Bill King"]
Todd Jones      [""]
Bill King       [""]
查詢Map
select name,deductions
from employees;
---
John Doe        {"Federal":0.2,"State":0.05,"Insurance":0.1}
Mary Smith      {"Federal":0.2,"State":0.05,"Insurance":0.1}
Todd Jones      {"Federal":0.15,"State":0.03,"Insurance":0.1}
Bill King       {"Federal":0.15,"State":0.03,"Insurance":0.1}        
查詢Struct
select name,address
from employees;
---
John Doe        {"street":"1 Michigan Ave.","City":"Chicago","state":"IL","zip":60600}
Mary Smith      {"street":"30 Michigan Ave.","City":"Chicago","state":"IL","zip":60600}
Todd Jones      {"street":"20 Michigan Ave.","City":"Chicago","state":"IL","zip":60600}
Bill King       {"street":"8 Michigan Ave.","City":"Chicago","state":"IL","zip":60600}   

引用集合數(shù)據(jù)類型中的元素

選取數(shù)組元素

注:string數(shù)據(jù)類型不再加引號

select name,subordinates[0]
from employees;
---
John Doe        Mary Smith
Mary Smith      Bill King
Todd Jones      NULL
Bill King       NULL
引用map元素
select name,deductions["State"]
from employees;
---
John Doe        0.05
Mary Smith      0.05
Todd Jones      0.03
Bill King       0.03  
引用struct的元素,使用“點(diǎn)”符號
select name,address.city
from employees;
---
John Doe        Chicago
Mary Smith      Chicago
Todd Jones      Oak Park
Bill King       Obscuria   

使用正則表達(dá)式制定列

select symbol,`price.*`
from stocks;
---
AAPL    195.69    197.88    194.0
AAPL    195.69    197.88    194.0
AAPL    195.69    197.88    194.0

使用列值進(jìn)行計算

select upper(name),salary,deductions["Federal"]
    ,round(salary * (1-deductions["Federal"]))
from employees;
---
JOHN DOE    10000.0    0.2    8000
MARY SMITH  8000.0     0.2    6400
JOHN DOE    7000.0     0.15   5950

算數(shù)運(yùn)算符

運(yùn)算符 類型 描述
A+B 數(shù)值 A和B相加
A-B 數(shù)值 A減去B
A*B 數(shù)值 A和B相乘
A/B 數(shù)值 A除以B。如果不能整除,那么返回商數(shù)。
A%B 數(shù)值 A除以B的余數(shù)。
A&B 數(shù)值 A和B按位取與。
A|B 數(shù)值 A和B按位取或。
A^B 數(shù)值 A和B按位取異或。
~A 數(shù)值 A按位取反。

注:

  1. 兩種類型數(shù)據(jù)計算:值范圍較小的數(shù)據(jù)類型將轉(zhuǎn)換為范圍更廣的數(shù)據(jù)類型。
  2. 需要注意數(shù)據(jù)溢出問題,數(shù)據(jù)溢出的計算結(jié)果不會自動轉(zhuǎn)換為更廣泛的數(shù)據(jù)類型

使用函數(shù)

數(shù)學(xué)函數(shù)

返回值類型 樣式 描述
bigint round(double d,int n) 返回保留n位小數(shù)的近似值
bigint floor(double d) 返回<=d的最大整數(shù)
bigint ceil(double d)
ceiling(double d)
返回>=d的最小整數(shù)
double rand()
rand(INT seed)
返回一個DOUBLE型的隨機(jī)數(shù),seed是隨機(jī)因子
double pow(double d,double p) 計算d的p次冪
double sqrt(double d) 計算d的平方根
double abs(double d) 計算d的絕對值
float sign(double d) 如果d是正數(shù),則返回 1.0;
如果d是負(fù)數(shù),則返回-1.0;
否則返回0.0

聚合函數(shù)

對多行進(jìn)行計算,返回一個結(jié)果值

返回值類型 樣式 描述
bigint count(*) 計算總行數(shù),包括含有NULL值的行
bigint count(expr) 計算expr表達(dá)式的值非NULL的行數(shù)
bigint count(distinct expr) 計算expr表達(dá)式的值排重后非NULL的行數(shù)
double sum(col) 計算制定行的值的和
double sum(distinct col) 計算排重后值的和
double avg(col) 計算指定行的值的平均值
double avg(distinct col) 計算排重后值的平均值
double min(col) 計算指定行的最小值
double max(col) 計算指定行的最大值
double percentile(bigint int_expr,p) int_expr在p(范圍是[0,1])的百分比數(shù)值點(diǎn)
array<double> percentile(bigint int_expr,array(p1[,p2]...)) int_expr在p(范圍是[0,1])的百分比數(shù)值點(diǎn)
double percentile_approx(bigint int_expr,p[,NB]) int_expr在p(范圍是[0,1])的百分比數(shù)值點(diǎn),NB是控制精度(默認(rèn)是10000)
array<double> percentile(bigint int_expr,array(p1[,p2]...)[, NB]) int_expr在p(范圍是[0,1])的百分比數(shù)值點(diǎn),NB是控制精度(默認(rèn)是10000)
array collect_set(col) 返回集合col元素排重后的數(shù)組

注:目前不允許在一個查詢語句中使用多于一個的函數(shù)(distinct ...)表達(dá)式

表生成函數(shù)

將單列拓展成多列或者多行

返回值類型 樣式 描述
N行結(jié)果 explode(array) 返回0到多行結(jié)果,每行都對應(yīng)輸入的array數(shù)組中的一個元素
N行結(jié)果 explode(map) 返回0到多行結(jié)果,每行對應(yīng)每個map鍵-值對
結(jié)果插入表中 inline(array<struct[,struct]>) 將結(jié)構(gòu)體數(shù)組提取出來并插入到表中
tuple json_tuple(string jsonstr,p1,p2,...,pn) 接受多個標(biāo)簽名稱,對輸入的json字符串進(jìn)行處理,
tuple parse_url_tuple(url,partname1,partname2,...) 從url中解析N個部分信息:HOST,PATH,QUERY,REF,PROTOCOL,AUTHORITY,FILE,USERINFO,QUERY:<KEY_NAME>
N行結(jié)果 stack(int n,col1,col2,...,colm) 把M列轉(zhuǎn)換成N行,每行有M/N個字段

注:explode不能和其他字段一起使用,比如select name,explode(map) from ee

Hive函數(shù)之explode和inline

其他內(nèi)置函數(shù)

返回值類型 樣式 描述
type cast(<expr> as <type>) 將expr轉(zhuǎn)換成type類型的,如果轉(zhuǎn)換失敗則返回null
string concat(str1,str2,...) 將字符串拼接成一個字符串,例如concat('ab','cd')的結(jié)果是'abcd'
string concat_ws(separator,str1,str2,...) 使用指定分隔符拼接字符串
int find_in_set(s,string) 返回以逗號分隔的字符串中s出現(xiàn)的位置
boolean in test in (val1,val2,...),其表示如果test等于后面任一值,則返回true
int length(str) 計算字符串的長度
int instr(str,substr) str字符串中substr第一次出現(xiàn)的位置
int locate(substr,str[,pos]) 查找字符串str中的pos位置后字符串sbustr第一次出現(xiàn)的位置
string lower(string) 轉(zhuǎn)換為小寫字母
string upper(string) 轉(zhuǎn)換為大寫字母
string regexp_replace(str,regex,replace) 按照java正則表達(dá)式regex將字符串str中符合條件的部分替換成replacement
string repeat(str,int) 重復(fù)輸出n次字符串s
string reverse(str) 反轉(zhuǎn)字符串
array<array<string>> sentences(str,str lang,str locale) 將輸入的字符串轉(zhuǎn)換成句子數(shù)組,每個句子由一個單詞數(shù)組構(gòu)成
int size(map<k.v>) 返回map中元素的個數(shù)
array<string> split(str,str pattern) 按照正則表達(dá)式pattern分割字符串,以字符串?dāng)?shù)組的方式返回
map<str,str> str_to_map(str,delim1,delim2) 將字符串s按照指定分隔符轉(zhuǎn)換成map
string substr(str,start_index,length) 從start位置截取length長度的字符串
string trim(str)
rtrim
ltrim
將字符串空格去掉

時間函數(shù)

返回值類型 樣式 描述
string from_unixtime(bigin T unixtime[, str format]) 將unix時間戳轉(zhuǎn)換成UTC時間,可通過format規(guī)定輸出的時間格式
bigint unix_timestamp() 獲取當(dāng)前本地時區(qū)下的當(dāng)前時間戳
bigint unix_timestamp(str date, str pattern) 將指定時間字符串格式字符串轉(zhuǎn)換成unix時間戳:unix_timestamp('2009-01-01','yyyy-MM-dd')
timestamp from_utc_timestamp(timestamp,timezone) 視同輸入UTC下的時間戳,返回指定時區(qū)的時間戳
timestamp to_utc_timestamp(timestamp,timezone) 視同輸入指定時區(qū)的時間戳,返回UTC下的時間戳
string to_date(str timestamp) 返回時間字符串的日期部分
int year(str date) 返回年份
int month(str date) 返回月份
int day(str date) 返回天
int hour(str date) 返回小時
int minute(str date) 返回分鐘
int second(str date) 返回秒數(shù)
int weekofyear(str date) 返回第幾周
int datediff(str enddate,str startdate) 相差的天數(shù)
str date_add(str startdate,int days) 增加天數(shù)
str date_sub(str startdate,int days) 減去天數(shù)

LIMIT語句

select  upper(name),salary,deductions["Federal"]
    ,round(salary * (1 - deductions["Federal"]))
from employees
limit 2;

列別名

select  upper(name),salary,deductions["Federal"] as fed_taxes
    ,round(salary * (1 - deductions["Federal"])) as salary_minus_fed_taxes
from employees
limit 2;

嵌套select語句

from (
select  upper(name),salary,deductions["Federal"] as fed_taxes
    ,round(salary * (1 - deductions["Federal"])) as salary_minus_fed_taxes
from employees
) e
select e.name,e.salary_minus_fed_taxes
where e.salary_minus_fed_taxes > 70000;

case...when...then...end 語句

select name,salary
    case
        when salary < 5000 then 'low'
        when salary < 7000 then 'middle'
        else 'high'
    end as bracket
from employees

where語句

select  upper(name),salary,deductions["Federal"] as fed_taxes
    ,round(salary * (1 - deductions["Federal"])) as salary_minus_fed_taxes
from employees
where round(salary * (1 - deductions["Federal"])) > 7000 //不可使用列別名

謂語操作符

運(yùn)算符 數(shù)據(jù)類型 描述
A = B 基本類型 如果表達(dá)A等于表達(dá)B,結(jié)果TRUE ,否則FALSE。
A <=> B 基本類型 如果A和B都為null則返回true,其他和(=)操作符結(jié)果一致。任一為null則結(jié)果為null
A != B
A <> B
所有基本類型 如果A不等于表達(dá)式B表達(dá)返回TRUE ,否則FALSE。
A < B 所有基本類型 TRUE,如果表達(dá)式A小于表達(dá)式B,否則FALSE。
A <= B 所有基本類型 TRUE,如果表達(dá)式A小于或等于表達(dá)式B,否則FALSE。
A > B 所有基本類型 TRUE,如果表達(dá)式A大于表達(dá)式B,否則FALSE。
A >= B 所有基本類型 TRUE,如果表達(dá)式A大于或等于表達(dá)式B,否則FALSE。
A [NOT] between B and C 如果表達(dá)式A大于或等于表達(dá)式B,小于或等于表達(dá)式C則返回true
A IS [NOT] NULL 所有類型 TRUE,如果表達(dá)式的計算結(jié)果為NULL,否則FALSE。
A [NOT] LIKE B 字符串 TRUE,如果字符串模式A匹配到B(簡單正則表達(dá)式),否則FALSE。%匹配任意數(shù)量字符,_匹配單個字符
A RLIKE B
A REGEXP B
字符串 NULL,如果A或B為NULL;TRUE,如果A任何子字符串匹配Java正則表達(dá)式B;否則FALSE。

注:一般來說A和B中任一為null,則返回null

關(guān)于浮點(diǎn)數(shù)比較

select *
from employees
where deductions['Federal'] > 0.2;
---
john 0.2
boss 0.3

為什么會返回0.2呢,這是因?yàn)橛脩魧懙母↑c(diǎn)數(shù)0.2,hive會默認(rèn)保存為double類型“0.200000000001”,而deductions是float類型的,將隱式轉(zhuǎn)換為double類型“0.200000100000”
如何避免呢:可以顯示的指出0.2是float類型

select *
from employees
where deductions['Federal'] > cast(0.2 as float);
---
boss 0.3

Group by 語句

group by語句通常和聚合函數(shù)一起使用,對分組進(jìn)行過濾

select year(ymd),avg(price_close)
from stocks
group by year(ymd)
having avg(price_close) > 50;

join 語句

select a.ymd, a.price_close, b.price_close
from stocks a
    join stocks b on a.ymd = b.ymd
where a.symbol = 'AAPL' and b.symbol = 'AAPL'

注:sql不支持“非等值連接”,也不支持在on子句中使用or。

join優(yōu)化

當(dāng)連接3個或更多表時,Hive會嘉定最后一個表時最大的表,然后嘗試將其它表緩存起來,然后掃面最后那個表進(jìn)行計算。
可以顯示的告訴Hive哪張表是達(dá)標(biāo):

select /*+STREAMTABLE(s)+*/a.ymd, a.price_close, b.price_close
from stocks a
    join stocks b on a.ymd = b.ymd
where a.symbol = 'AAPL' and b.symbol = 'AAPL'
其他join
  • left outer join
  • outer join
  • right outer join
  • full outer join

注:where語句在連接操作執(zhí)行后才會執(zhí)行

left semi-join

比inner join更高效的查詢方式,但是只能引用左邊表的字段

select s.ymd, s.symbol, s.price_close
from stocks s 
    left semi join dividends d on s.ymd = d.ymd and s.symbol = d.symbol; 
排序 order by 和 sort by

order by 全局排序

select s.ymd, s.symbol, s.price_close
from stocks s
order by s.ymd asc ,s.symbol desc

sort by 只在reducer內(nèi)部排序,如果有多個reducer,則不保證輸出的是整體有序的。

select s.ymd, s.symbol, s.price_close
from stocks s
sort by s.ymd asc ,s.symbol desc

使用distribute by來保證相同的數(shù)據(jù)會分發(fā)到同一個reducer中進(jìn)行處理:

select s.ymd, s.symbol, s.price_close
from stocks s
distribute by s.symbol    --同一個symbol放到同一個reducer中處理
sort by s.symbol, s.ymd desc

如果上面的語句沒有要求按ymd 倒序排列,則可以用cluster by簡化:

select s.ymd, s.symbol, s.price_close
from stocks s
cluster by s.symbol 

類型轉(zhuǎn)換

cast(value as TYPE)

抽樣查詢

分桶抽樣
分子是要分為幾桶,分子是取回的第幾個桶,rand()表示隨機(jī)排序(如果省略rand(),則返回的結(jié)果會始終一致)

select *
from numbers tablessample(bucket 1 out of 2 on rand()) s;
---
2
4
6
8
10
數(shù)據(jù)塊抽樣
select *
from numbersflat tablesample(0.1 percent) s;

union all 語句

將兩個或多個表進(jìn)行合并,但是要求對應(yīng)的字段類型必須一致。

分析函數(shù)

分析函數(shù)用于計算基于組的某種聚合值,它和聚合函數(shù)的不同之處是:對于每個組返回多行,而聚合函數(shù)對于每個組只返回一行。
基本結(jié)構(gòu):

分析函數(shù)() + over(partition by ** order by ** rows between ** and **)

基礎(chǔ)數(shù)據(jù).png
SELECT cookieid,createtime,pv,
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS pv1, -- 默認(rèn)為從起點(diǎn)到當(dāng)前行
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS pv2, --從起點(diǎn)到當(dāng)前行,結(jié)果同pv1 
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pv3,   --當(dāng)前行+往前3行
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) AS pv4,    --當(dāng)前行+往前3行+往后1行
SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS pv5   ---當(dāng)前行+往后所有行  
FROM test1;
-----
cookieid    createtime  pv  pv1  pv2    pv3  pv4  pv5
a           2017-12-01  3    3    3      3    3    3
b           2017-12-00  3    3    3      3    3    3
cookie1     2017-12-10  1    1    1      1    6    26
cookie1     2017-12-11  5    6    6      6    13   25
cookie1     2017-12-12  7    13  13      13   16   20
cookie1     2017-12-13  3    16  16      16   18   13
cookie1     2017-12-14  2    18  18      17   21   10
cookie1     2017-12-15  4    22  22      16   20   8
cookie1     2017-12-16  4    26  26      13   13   4
cookie2     2017-12-12  7    7    7      7    13   14
cookie2     2017-12-16  6    13  13      13   14   7
cookie2     2017-12-24  1    14  14      14   14   1
cookie3     2017-12-22  5    5    5      5     5   5

行數(shù)控制(window子句):

  • preceding:往前
  • FOLLOWING:往后
    CURRENT ROW:當(dāng)前行
    UNBOUNDED:無邊界,UNBOUNDED PRECEDING 表示從最前面的起點(diǎn)開始, UNBOUNDED FOLLOWING:表示到最后面的終點(diǎn)

開窗函數(shù)

sum

sum()計算的是分區(qū)內(nèi)排序后一個個疊加的值,和order by有關(guān);如果沒有order by,不僅分區(qū)內(nèi)沒有排序,sum()計算的pv也是整個分區(qū)的pv

select cookieid,createtime,pv,
    sum(pv) over(PARTITION BY cookieid ORDER BY createtime) as pv1 
FROM test1
max

返回最大值

min

返回最小值

ntile

NTILE(n),用于將分組數(shù)據(jù)按照順序切分成n片,返回當(dāng)前切片值
注1:如果切片不均勻,默認(rèn)增加第一個切片的分布
注2:NTILE不支持ROWS BETWEEN

SELECT cookieid,createtime,pv,
NTILE(2) OVER(ORDER BY createtime) AS ntile1, --分組內(nèi)將數(shù)據(jù)分成2片
NTILE(3) OVER(ORDER BY createtime) AS ntile2,  --分組內(nèi)將數(shù)據(jù)分成3片
NTILE(4) OVER(ORDER BY createtime) AS ntile3   --將所有數(shù)據(jù)分成4片
FROM test1 
row_number

row_number() 從1開始,按照順序,生成分組內(nèi)記錄的序列
類似:

  • rank() 生成數(shù)據(jù)項在分組中的排名,排名相等會在名次中留下空位
  • dense_rank() 生成數(shù)據(jù)項在分組中的排名,排名相等會在名次中不會留下空位
SELECT cookieid,createtime,pv,
    rank() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rank1,
    dense_rank() OVER(PARTITION BY cookieid ORDER BY pv desc) AS d_rank2,
    row_number() OVER(PARTITION BY cookieid ORDER BY pv DESC) AS rn3 
FROM test1 
cume_dist

返回:
{小于等于當(dāng)前值的行數(shù) \over 分組內(nèi)總行數(shù)}
比如,我們可以統(tǒng)計小于等于當(dāng)前薪水的人數(shù),所占總?cè)藬?shù)的比例

SELECT cookieid,createtime,pv,
    round(cume_dist() OVER(ORDER BY pv),2) AS cd1,
    round(cume_dist() OVER(PARTITION BY cookieid ORDER BY pv),2) AS cd2  
FROM test1;

類似的:percent_rank,返回:
{小于等于當(dāng)前值的行數(shù)-1 \over 分組內(nèi)總行數(shù)-1}

LAG 和 LEAD

LAG(col,n,DEFAULT) 用于統(tǒng)計窗口內(nèi)往上第n行值,第一個參數(shù)為列名,第二個參數(shù)為往上第n行(可選,默認(rèn)為1),第三個參數(shù)為默認(rèn)值(當(dāng)往上第n行為NULL時候,取默認(rèn)值,如不指定,則為NULL)

LEAD 函數(shù)則與 LAG 相反: LEAD(col,n,DEFAULT) 用于統(tǒng)計窗口內(nèi)往下第n行值

SELECT cookieid,createtime,pv,
    ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
    LAG(createtime,1,'1970-01-01') OVER(PARTITION BY cookieid ORDER BY createtime) AS lag1,
    LAG(createtime,2) OVER(PARTITION BY cookieid ORDER BY createtime) AS lag2 
FROM test1;
FIRST_VALUE 和 LAST_VALUE

FIRST_VALUE 取分組內(nèi)排序后,截止到當(dāng)前行,第一個值;
LAST_VALUE 函數(shù)則相反,取分組內(nèi)排序后,截止到當(dāng)前行,最后一個值。

SELECT cookieid,createtime,pv,
    ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
    FIRST_VALUE(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS first  
FROM test1;

窗口函數(shù)參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容