GreenPlum数开手册【语法篇】

GreenPlum数开手册

一、数据类型

1、基本数据类型

类型长度描述范围
bigint8字节大范围整数-9223372036854775808 到 +9223372036854775807
smallint2字节小范围整数-32768到+32767
integer(int)4字节常用整数-2147483648 到 +2147483647
decimal可变长用户指定的精度,精确小数点前 131072 位;小数点后 16383 位
real4字节可变精度,不准确6位十进制数字精度
double precision8字节可变精度,不准确15位十进制数字精度
smallserial2字节自增的小范围整数1到32767
serial4字节自增整数1到2147483647
bigserial8字节自增的大范围整数1到9223372036854775807
character别名char定长,不足补空白
character varying别名archar变长,有长度限制
text变长,无长度限制
timestamp8字节日期和时间,无时区4713 BC到294276 AD
timestamp with time zone8字节日期和时间,有时区4713 BC到294276 AD
date4字节只用于日期4713 BC到5874897 AD
boolean1字节true/false
money8字节货币金额-92233720368547758.08 到 +92233720368547758.07

2、复杂数据类型

2.1、枚举类型

枚举类型是一个包含静态和值的有序集合的数据类型,类似于Java中的enum类型,需要使用create type命令创建。

-- 创建枚举类型
create type weeks as enum('Mon','Tue','Wed','Thu','Fri','Sat','Sun');

-- 建表字段使用枚举类型
create table user_schedule (
    user_name varchar(100),
    available_day weeks
);

-- 插入数据
insert into user_schedule (user_name, available_day) values ('Alice', 'Mon');
insert into user_schedule (user_name, available_day) values ('Bob', 'Fri');
insert into user_schedule (user_name, available_day) values ('Charlie', 'Sun');

-- 查询结果
select * from user_schedule;

2.2、几何类型

几何数据类型表示二维的平面物体。下表列出了GreenPlum支持的几何类型。

最基本的类型:点。它是其它类型的基础。

类型大小描述表现形式
point16字节平面中的点(x,y)
line32字节直线((x1,y1),(x2,y2))
lseg32字节线段((x1,y1),(x2,y2))
box32字节矩形((x1,y1),(x2,y2))
path16+16n字节路径(与多边形相似)((x1,y1),…)
polygon40+16n字节多边形((x1,y1),…)
circle24字节<(x,y),r> (圆心和半径)
-- 建表 创建一个表 geometric_shapes,它包含点、线和多边形类型的列。
create table geometric_shapes (
    id serial primary key,
    point_col point,
    lseg_col lseg,
    polygon_col polygon
);

-- 插入数据
insert into geometric_shapes (point_col, lseg_col, polygon_col)
values
(point(1, 2), lseg '[(0,0),(1,1)]', polygon '((0,0),(1,0),(1,1),(0,1))');

-- 查询数据
--- 查询所有
select * from geometric_shapes;

--- 根据点查询
select * from geometric_shapes where point_col <-> point(1, 2) < 0.0001;

--- 根据线段查询
select * from geometric_shapes where lseg_col = lseg '[(0,0),(1,1)]';

--- 根据多边形查询
select * from geometric_shapes where polygon_col ~= polygon '((0,0),(1,0),(1,1),(0,1))';

2.3、网络地址类型

GreenPlum提供用于存储IPv4、IPv6、MAC地址的数据类型。用这些数据类型存储网络地址比用纯文本好,因为提供输入错误检查和特殊的操作和功能。

类型描述说明
cidr7或19字节IPv4 或 IPv6 网络
inet7或19字节IPv4 或 IPv6 主机和网络
macaddr6字节MAC 地址

在对 inet 或 cidr 数据类型进行排序的时候, IPv4 地址总是排在 IPv6 地址前面。

-- 创建包含网络地址数据类型的表
create table network_addresses (
    id serial primary key,
    ip_address inet,
    network cidr,
    mac_address macaddr
);

-- 插入数据
insert into network_addresses (ip_address, network, mac_address)
values
('192.168.1.1/24', '192.168.1.0/24', '08:00:2b:01:02:03');

-- 查询数据
select * from network_addresses;

-- 查询特定的 IP 地址
select * from network_addresses where ip_address = inet '192.168.1.1';
select * from network_addresses where host(ip_address) = '192.168.1.1';

-- 查询特定的网络
select * from network_addresses where network = cidr '192.168.1.0/24';

-- 查询特定的 MAC 地址
select * from network_addresses where mac_address = macaddr '08:00:2b:01:02:03';

-- 更新数据
update network_addresses set ip_address = inet '192.168.1.2' where id = 1;

-- 删除数据
delete from network_addresses where id = 1;

2.4、JSON类型

json 数据类型可以用来存储 JSON(JavaScript Object Notation)数据, 这样的数据也可以存储为 text,但是 json 数据类型更有利于检查每个存储的数值是可用的 JSON 值。

此外还有相关的函数来处理 json 数据:

-- 创建一个新表,名为 json_demo,包含一个 json 类型的列
create table json_demo (
    id serial primary key,
    data json
);

-- 向 json_demo 表插入 json 数据,注意 json 数据必须是单引号的字符串
-- 并且遵循 json 格式
insert into json_demo (data) values ('{"name": "张三", "age": 28, "city": "北京"}');

-- 查询 json_demo 表中的 json 数据
select * from json_demo;

-- 使用 ->> 运算符来提取 json 对象中的 name 字段
select data->>'name' as name from json_demo;

2.5、数组类型

GreenPlum允许将字段定义成变长的多为数组。数组可以是任何基本类型或用户定义类型,枚举类型或复合类型。

-- 创建一个新表,名为 array_demo,包含一个 int 类型的数组列
create table array_demo (
    id serial primary key,
    numbers int[]  -- int 数组类型列
);

-- 向 array_demo 表插入数组数据
-- 数组使用花括号{}并且元素由逗号分隔
insert into array_demo (numbers) values ('{1,2,3,4,5}');

-- 查询 array_demo 表中的数组数据
select * from array_demo;

-- 使用数组下标来获取数组中的特定元素
-- 注意:Greenplum数组下标从1开始
select numbers[1] as first_element from array_demo;

-- 使用 unnest 函数来展开数组为一系列行
select unnest(numbers) as expanded_numbers from array_demo;

2.6、复合类型

复合类型表示一行或者一条记录的结构; 它实际上只是一个字段名和它们的数据类型的列表。GreenPlum允许像简单数据类型那样使用复合类型。比如,一个表的某个字段可以声明为一个复合类型。

定义复合类型,语法类似于create table,只是这里可以声明字段名字和类型。

-- 定义一个复合类型,名为 person_type,包含姓名、年龄和城市
create type person_type as (
    name text,
    age int,
    city text
);

-- 创建一个新表,名为 composite_demo,包含一个复合类型的列
create table composite_demo (
    id serial primary key,
    person_info person_type  -- 使用之前定义的复合类型作为列类型
);

-- 向 composite_demo 表插入复合类型数据
-- 复合类型数据使用括号,并且属性值由逗号分隔
insert into composite_demo (person_info) values (ROW('张三', 28, '北京'));

二、DDL

2.1、创建数据库

2.1.1、语法

CREATE DATABASE name [ [WITH] [OWNER [=] dbowner]
[TEMPLATE [=] template]
[ENCODING [=] encoding]
[TABLESPAC [=] tablespace]
[CONNECTIONE LIMIT [=] connlimit ] ]

CREATE DATABASE name:

CREATE DATABASESQL 命令,用于创建一个新的数据库。
name 是你要创建的数据库的名称。这个名称是必须的,并且在同一个数据库服务器上必须是唯一的。

[ [WITH] [OWNER [=] dbowner]:
这是一个可选项。
OWNER 指定了新数据库的所有者。如果未指定,新数据库的所有者默认是执行该命令的用户。
dbowner 是数据库所有者的用户名。

[TEMPLATE [=] template]:
这也是一个可选项。
TEMPLATE 指定了用于创建新数据库的模板。在 PostgreSQL 和 GreenPlum 中,通常有一个名为 template1 的默认模板。如果不指定,就会使用这个默认模板。
template 是模板数据库的名称。

[ENCODING [=] encoding]:
又一个可选项。
ENCODING 指定了新数据库的字符编码。这个设置决定了数据库可以存储哪些字符。
encoding 是字符编码的名称,例如 UTF8。

[TABLESPACE [=] tablespace]:
这是可选的。
TABLESPACE 指定了新数据库的存储位置。表空间是数据库中存储文件的物理位置。
tablespace 是表空间的名称。

[CONNECTION LIMIT [=] connlimit ]:
这也是可选的。
CONNECTION LIMIT 限制了可以同时连接到数据库的最大客户端数量。
connlimit 是允许的最大连接数。如果设置为 -1,则表示没有限制。

2.1.2、实例

create database my_db1
with owner gpadmin
encoding 'utf-8'
tablespace pg_default
connection limit 10; 

2.1.3、创建schema

schema 本质上就是一种分组管理工具,它允许您将相关性质或类型的多个表和其他数据库对象(如视图、索引、存储过程等)组织在一起。也可以把 schema 看作是数据库内部的一个“文件夹”或“命名空间”,用于逻辑上组织和隔离数据,以实现更好的数据管理和安全控制。

一个 database 下可以有多个 schema。schema在 gp 中也叫做 namespace。

-- 连接创建完成的数据库
\c EmployeeDB

-- 创建schema
create schema sc_test;

2.2、查询数据库

  • 显示数据库

    -- 仅greenplum命令行客户端支持
    \l   --查看所有数据库
    \dn  --查看所有schema
    
    -- 可视化客户端中使用以下操作
    -- 列出 PostgreSQL 实例中所有数据库的名称 
    select datname from pg_database;
    
    -- 查询schema 
    SELECT schema_name FROM information_schema.schemata;
    
  • 切换当前数据库

    -- 仅greenplum命令行客户端支持
    \c db_gp
    

2.3、删除数据库

DROP DATABASE 会删除数据库的系统目录项并且删除包含数据的文件目录。

如果删除的数据库不存在,最好采用 if exists判断数据库是否存在。

drop database if exists db_gp;

2.4、创建表

2.4.1、建表语法

CREATE [EXTERNAL] TABLE table_name(
 column1 datatype [NOT NULL] [DEFAULT] [CHECK] [UNIQUE],
 column2 datatype,
 column3 datatype,
 .....
 columnN datatype,
 [PRIMARY KEY()]
)[ WITH ()]
 [LOCATION()]
 [FORMAT]
 [COMMENT]
 [PARTITION BY]
 [DISTRIBUTE BY ()];

如果建表时会提示Table doesn’t have ‘DISTRIBUTED BY’ clause – Using column named ‘id’ as the Greenplum Database data distribution key for this table.这是提醒建表时指定分布键和分布策略,默认第一个字段(或逐渐)和hash策略。

2.4.2、字段解释说明

(1)create table创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;

(2)external关键字可以让用户创建一个外部表,在建表的同时可以指定一个指向实际数据的路径(location)。

(3)comment:为表和列添加注释。

(4)distributed b****y 为表添加分布键,其必须为主键的子键。

(5)format 存储数据的文本类型。

(6)check 为表字段添加检查约束。

(7)unique 唯一约束,一个表中唯一和主键只能同时存在一个。

(8)primary key 主键设置,可以是一个或多个列。

(9)location:指定外部表数据存储位置。

(10)default:默认值。

(11)not null非空约束。

(12)with 可以添加数据追加方式,压缩格式,压缩级别,行列压缩等。

(13)partiton by 支持两种分区方式,范围分区(range)和列表分区(list)

2.4.3、内部表和外部表的介绍

内部表和外部表是两种不同类型的表,它们在数据存储和处理方式上有明显的区别。了解这些区别对于合理地设计和优化 GreenPlum 数据库是非常重要的。

  1. 内部表(Regular Tables)

    **数据存储:**内部表的数据直接存储在 GreenPlum 数据库的数据文件中。这意味着数据被物理存储在数据库服务器上。

    **事务管理:**内部表完全支持事务管理。这包括 ACID 属性(原子性、一致性、隔离性和持久性),确保数据完整性和可靠性。

    **索引和约束:**你可以在内部表上创建索引和约束,这有助于提高查询性能和维护数据完整性。

    **管理和维护:**内部表可以使用数据库的全部管理和维护功能,如备份和恢复。

    **适用性:**适用于需要高性能查询和事务完整性的数据。

  2. 外部表(External Tables)

    **数据存储:**外部表的数据存储在数据库外部,如在文件系统、Hadoop HDFS 或任何可通过 SQL/MED(SQL Management of External Data)访问的数据源。外部表仅存储数据的元数据和位置信息。

    **事务管理:**外部表不支持事务管理。它们主要用于读取和加载操作,不保证 ACID 属性。

    **索引和约束:**由于数据实际存储在外部,你不能在外部表上创建索引或强制执行数据库级别的约束。

    **管理和维护:**外部表的管理相对简单,因为它们只是对外部数据源的引用。备份和恢复通常不适用于外部表本身,而是应用于数据源。

    **适用性:**适用于 ETL(Extract, Transform, Load)操作,即从外部数据源提取数据,然后可能将其转换和加载到内部表中进行进一步处理。

案例实现:

一:内部表操作	
-- 创建内部表
CREATE TABLE employees ( employee_id SERIAL PRIMARY KEY, name VARCHAR(100), department VARCHAR(100), hire_date DATE );

-- 插入数据
INSERT INTO employees (name, department, hire_date) VALUES ('John Doe', 'IT', '2020-01-01');
INSERT INTO employees (name, department, hire_date) VALUES ('Jane Smith', 'HR', '2020-02-01');

-- 查询结果
SELECT * FROM employees;


二:外部表操作
假设我们有一个 CSV 文件 employee_data.csv,它存储在文件系统中,格式如下:
employee_id,name,department,hire_date
1,John Doe,IT,2020-01-01
2,Jane Smith,HR,2020-02-01

-- 开启一个静态文件服务
gpfdist -d /home/gpadmin/software/datas/ -p 8081 &


-- 创建外部表
CREATE EXTERNAL TABLE ext_employees (
    employee_id varchar(100),
    name VARCHAR(100),
    department VARCHAR(100),
    hire_date varchar(100)
)
LOCATION ('gpfdist://hadoop102:8081/employee_data.csv')
FORMAT 'CSV';


SELECT * FROM ext_employees;

体现内外表区别的操作

内部表:
可以对内部表进行 INSERT, UPDATE, DELETE 等操作,因为数据存储在数据库内部。
支持事务,可以回滚未提交的更改。
可以创建索引以提高查询性能。

外部表:
通常只用于 SELECT 操作,用于读取外部数据源的数据。
不支持事务。
不支持索引创建。

内部表和外部表在操作和用途上的主要区别。内部表适合存储和管理数据库内的数据,而外部表适用于从外部数据源临时读取数据。

2.5、修改表

2.5.1、重命名表

1)语法
ALTER TABLE table_name RENAME TO new_table_name
2)实操案例
gpdw=# alter table arr_test rename to arr;

2.5.2、增加/修改/替换列信息

1)语法

(1)更新列

修改列明 ALTER TABLE tab_name RENAME old_name TO new_name;
修改列类型 ALTER TABLE tab_name ALTER COLUMN column_name TYPE column_type [USING column_name::column_type];

(2)增加/删除列

ALTER TABLE table_name ADD|DROP COLUMN col_name [column_type];

注:ADD是代表新增一个字段,需要添加相应的字段类型,DROP是代表删除一个字段。

2)实操案例

(1)查询表结构

gpdw=# \d arr

(2)添加列

gpdw=# gpdw=# alter table arr add column id int;

(3)更新列

gpdw=# alter table arr rename sal to salary;
gpdw=# alter table arr alter column id type double precision;

(4)删除列

gpdw=# alter table arr drop column id;

2.6、删除表

gpdw=# drop table arr;

2.7、清除表

注意:truncate只能删除内部表,不能删除外部表中数据。

gpdw=# truncate table arr;

三、DML

3.1 数据导入

3.1.1 向表中装载数据(COPY)

1)语法

COPY table_name FROM file_path DELIMITER ‘字段之间的分隔符’;
  • (1)copy:表示加载数据,仅追加。
  • (2)delimiter:表示读取的数据字段之间的分隔符。

2)实操案例
(0)准备一份文件 在hadoop102的/home/gpadmin/software/datas目录下新建文件

vim employees1.txt   内容如下:
John,IT,30
Jane,HR,25

(1)创建一张表

CREATE TABLE employees1 (
    name VARCHAR(100),
    department VARCHAR(50),
    age INTEGER
);

(2)加载文件到表中

COPY employees1 FROM '/home/gpadmin/software/datas/employees1.txt' delimiter ',';

3.1.2 通过查询语句向表中插入数据(Insert)

1)创建一张表

CREATE TABLE employees2 (
    name VARCHAR(100),
    department VARCHAR(50),
    age INTEGER
);

2)基本模式插入数据

insert into  employees2  values(‘zhangsan’,'IT',18),(‘lisi’,'HR',20);

3)根据查询结果插入数据

insert into  employees2 select * from employees1;

注意:insert不支持覆盖数据,仅追加。

3.1.3 查询语句中创建表并加载数据(As Select)

根据查询结果创建表(查询的结果会添加到新创建的表中)。

create table employees3 as select * from employees1 ;

3.2 数据更新和删除

3.2.1 数据更新

修改数据的通用SQL语法:

UPDATE table_name
SET column1 = value1, column2 = value2...., columnN = valueN
WHERE [condition];

我们可以同时更新一个或多个字段,也可以在WHERE子句中指定任何条件。

update employees3 set name='haihai' where department = 'HR';

3.2.2 数据删除

删除指定数据的通用SQL语法:

DELETE FROM table_name WHERE [condition];

如果没有指定 WHERE 子句,GreenPlum对应表中的所有记录将被删除。
一般我们需要在 WHERE 子句中指定条件来删除对应的记录,条件语句可以使用 AND 或 OR 运算符来指定一个或多个。

delete from gp_test where id =1 or name = 'cangcang';

3.2.3 创建外部表时通过Location指定加载数据路径

1)数据存储在segment节点,不要在master节点
2)创建表,并指定文件位置

create external table gp_test3 (
id int, 
name text
) location('file://hadoop103:6000/opt/greenplum/data1/primary/gp_test.txt') 
format 'text' (delimiter ',');

3)查询数据

select * from gp_test3;

后续只需要文件修改,对应查出的数据即会随着改变。

3.3 数据导出

无法导出外部表的数据。

copy employees3 to '/home/gpadmin/software/datas/test.txt';

四、DQL

4.1 基础语法及执行顺序

1)查询语句语法:

SELECT [DISTINCT] colum1, column2, ...
FROM table_name               -- 从什么表查
[WHERE condition]             -- 过滤
[GROUP BY column_list]        -- 分组查询
[HAVING column_list]          -- 分组后过滤
[ORDER BY column_list]        -- 排序
[LIMIT number] 

4.2 基本查询(Select…From)

4.2.1 数据准备

(0)原始数据

①在/home/gpadmin/software/datas/路径上创建dept.txt文件,并赋值如下内容:
部门编号 部门名称 部门位置id
[atguigu@hadoop103 data]$ vim dept.txt
10,行政部,1700
20,财务部,1800
30,教学部,1900
40,销售部,1700
②在/home/gpadmin/software/datas/路径上创建emp.txt文件,并赋值如下内容:
员工编号 姓名 岗位 薪资 部门
[atguigu@hadoop103 data]$ vim emp.txt
7369,张三,研发,800.00,30
7499,李四,财务,1600.00,20
7521,王五,行政,1250.00,10
7566,赵六,销售,2975.00,40
7654,侯七,研发,1250.00,30
7698,马八,研发,2850.00,30
7782,金九,,2450.0,30
7788,银十,行政,3000.00,10
7839,小芳,销售,5000.00,40
7844,小明,销售,1500.00,40
7876,小李,行政,1100.00,10
7900,小元,讲师,950.00,30
7902,小海,行政,3000.00,10
7934,小红明,讲师,1300.00,30

(1)创建部门表
create external table dept (
deptno int,   --部门编号
dname text,   --部门名称
loc int       --部门位置id
) location('gpfdist://hadoop102:8081/dept.txt') 
format 'text' (delimiter ',');
(2)创建员工表
create external table emp (
empno int,             -- 员工编号
ename text,            -- 员工姓名
job text,              -- 员工岗位(大数据工程师、前端工程师、java工程师)
sal double precision,  -- 员工薪资
deptno int             -- 部门编号
) location('gpfdist://hadoop102:8081/emp.txt') 
format 'text' (delimiter ',');

4.2.2 全表和特定列查询

1)全表查询

select * from emp ;

2)选择特定列查询

select empno,ename from emp ;

4.2.3 列别名

1)重命名一个列
2)便于计算
3)紧跟列名,也可以在列名和别名之间加入关键字‘AS’
4)查询名称和部门。

select
    ename as name,
    deptno dn
from emp;

4.2.4 Limit语句

典型的查询会返回多行数据。limit子句用于限制返回的行数。

select * from emp limit 2; 
select * from emp limit 2 offset 3;  --表示从第二行开始,向下抓取三行数据。

4.2.5 Where语句

1)使用where子句,将不满足条件的行过滤掉
2)where子句紧随from子句
3)查询出薪水大于1000的所有员工。

select * from emp where sal > 1000;

注意:where子句中不能使用字段别名。

4.2.6 关系运算函数

1)基本语法

如下操作符主要用于where、join…on和having语句中。

操作符支持的数据类型描述
A=B基本数据类型如果A等于B则返回true,反之返回false
A<=>B基本数据类型如果A和B都为null,则返回true,如果一边为null,返回false
A<>B, A!=B基本数据类型A或者B为null则返回null;如果A不等于B,则返回true,反之返回false
A<B基本数据类型A或者B为null,则返回null;如果A小于B,则返回true,反之返回false
A<=B基本数据类型A或者B为null,则返回null;如果A小于等于B,则返回true,反之返回false
A>B基本数据类型A或者B为null,则返回null;如果A大于B,则返回true,反之返回false
A>=B基本数据类型A或者B为null,则返回null;如果A大于等于B,则返回true,反之返回false
A [not] between B and C基本数据类型如果A,B或者C任一为null,则结果为null。如果A的值大于等于B而且小于或等于C,则结果为true,反之为false。如果使用not关键字则可达到相反的效果。
A is null所有数据类型如果A等于null,则返回true,反之返回false
A is not null所有数据类型如果A不等于null,则返回true,反之返回false
in(数值1,数值2)所有数据类型使用 in运算显示列表中的值
A [not] like Bstring 类型B是一个SQL下的简单正则表达式,也叫通配符模式,如果A与其匹配的话,则返回true;反之返回false。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母‘x’结尾,而‘%x%’表示A包含有字母‘x’,可以位于开头,结尾或者字符串中间。如果使用not关键字则可达到相反的效果。
A rlike B, A regexp Bstring 类型B是基于java的正则表达式,如果A与其匹配,则返回true;反之返回false。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。
2)案例实操(between/In/ Is null)

(1)查询出薪水等于5000的所有员工
select * from emp where sal = 5000;
(2)查询工资在500到1000的员工信息
select * from emp where sal between 500 and 1000;
(3)查询job为空的所有员工信息
select * from emp where job is null;
(4)查询工资是1500或5000的员工信息
select * from emp where sal in (1500,5000);
(5)查找名字以“明”结尾的员工信息
select * from emp where ename like '%明';

4.2.7 逻辑运算函数

1)基本语法(and/or/not)
操作符含义
and逻辑并
or逻辑或
not逻辑否
2)案例实操

(1)查询薪水大于1000,部门是30

select                                   
*
from emp
where sal > 1000 and deptno = 30;

(2)查询薪水大于1000,或者部门是30

select 
    * 
from emp 
where sal>1000 or deptno=30;

(3)查询除了20部门和30部门以外的员工信息

select 
    * 
from emp 
where deptno not in(30, 20);

4.2.8 聚合函数

1)语法

count(),表示统计行数;
max(),求最大值,不包含null,除非所有值都是null;
min(),求最小值,不包含null,除非所有值都是null;
sum(),求和,不包含null。
avg(),求平均值,不包含null。

2)案例实操

(1)求总行数(count)
select count(*) from emp;
(2)求工资的最大值(max)
select max(sal) max_sal from emp;
(3)求工资的最小值(min)
select min(sal) min_sal from emp;
(4)求工资的总和(sum)
select sum(sal) sum_sal from emp;
(5)求工资的平均值(avg)
select avg(sal) avg_sal from emp;

4.3 分组

4.3.1 Group By语句

Group By语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作。
查询时如果SQL语句中含有group by,那么select后查询的字段只能包含出现在group by后面的字段。

1)案例实操:

(1)计算emp表每个部门的平均工资。

select 
    t.deptno, 
    avg(t.sal) avg_sal 
from emp t 
group by t.deptno;

(2)计算emp每个部门中每个岗位的最高薪水。

select 
    t.deptno, 
    t.job, 
    max(t.sal) max_sal 
from emp t 
group by t.deptno, t.job;

4.3.2 Having语句

1)having与where不同点
(1)where后面不能写分组聚合函数,而having后面可以且只能使用分组聚合函数,不可使用聚合函数的别名。
(2)having只用于group by分组统计语句。
2)案例实操
(1)求每个部门的平均薪水大于2000的部门

select 
    deptno, 
    avg(sal) avg_sal 
from emp 
group by deptno  
having avg(sal) > 2000;

4.4 Join语句

4.4.1 等值Join

GreenPlum支持通常的sql join语句。

1)案例实操
(1)根据员工表和部门表中的部门编号相等,查询员工编号、员工名称和部门名称。

select 
    e.empno, 
    e.ename, 
    d.dname 
from emp e 
join dept d 
on e.deptno = d.deptno;

4.4.2 内连接

内连接:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。默认的join即为inner join。

select 
    e.empno, 
    e.ename, 
    d.deptno 
from emp e 
join dept d 
on e.deptno = d.deptno;

4.4.3 左外连接

左外连接:join操作符左边表中所有记录将会被返回,右表匹配不到的置为null。

select 
    e.empno, 
    e.ename, 
    d.deptno 
from emp e 
left join dept d 
on e.deptno = d.deptno;

4.4.4 右外连接

右外连接:join操作符右边表中所有记录将会被返回,左表匹配不到的置为null。

select 
    e.empno, 
    e.ename, 
    d.deptno 
from emp e 
right join dept d 
on e.deptno = d.deptno;

4.4.5 满外连接

满外连接:将会返回所有表中所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用null值替代。

select 
    e.empno, 
    e.ename, 
    d.deptno 
from emp e 
full join dept d 
on e.deptno = d.deptno;

4.4.6 多表连接

注意:连接n个表,至少需要n-1个连接条件。例如:连接三个表,至少需要两个连接条件。
数据准备,在/opt/module/data/下:vim location.txt
部门位置id 部门位置

[atguigu@hadoop102 datas]$ vim location.txt
1700,北京
1800,上海
1900,深圳
1)创建位置表
create external table location (
loc int,        --部门位置id
loc_name text   --部门位置
) location('gpfdist://hadoop102:8081/location.txt') 
format 'text' (delimiter ',');
2)多表连接查询
select 
    e.ename, 
    d.dname, 
    l.loc_name
from emp e 
join dept d
on d.deptno = e.deptno 
join location l
on d.loc = l.loc;

4.4.7 笛卡尔积

1)笛卡尔集会在下面条件下产生
(1)省略连接条件
(2)连接条件无效
(3)所有表中的所有行互相连接
2)案例实操

select 
    empno, 
    dname 
from emp, dept;

4.4.8 联合(union & union all)

1)union&union all上下拼接
union和union all都是上下拼接sql的结果,这点是和join有区别的,join是左右关联,union和union all是上下拼接,且前者会去重,后者不会进行去重。
union和union all在上下拼接sql结果时有两个要求:
(1)两个sql的结果,列的个数必须相同
(2)两个sql的结果,上下所对应列的类型必须一致
2)案例实操
将员工表30部门的员工信息和40部门的员工信息,利用union进行拼接显示。

select 
    *
from emp
where deptno=30
union
select 
    *
from emp
where deptno=40;

4.5 排序

Order By:全局排序。

1)使用Order By子句排序
asc(ascend):升序(默认)
desc(descend):降序
2)Order By子句一般放在在select语句的结尾,其后所跟字段可以是别名或者多个字段。
3)基础案例实操
(1)查询员工信息按工资升序,部门降序排列

select
deptno dn,
sal
from emp
order by dn desc,sal asc;

五、函数

5.1 函数简介

​ GreenPlum会将常用的逻辑封装成函数给用户进行使用,类似于Java中的方法。
**好处:**避免用户反复写逻辑,可以直接拿来使用。
**重点:**用户需要知道函数叫什么,能做什么。
​ 提供了大量的内置函数,按照其特点可大致分为如下几类:单行函数、聚合函数(行转列)、炸裂函数(列转行)、窗口函数。

5.2 单行函数

单行函数的特点是一进一出,即输入一行,输出一行。

5.2.1 算术运算函数

运算符描述
A+BA和B 相加
A-BA减去B
A*BA和B 相乘
A/BA除以B
A%BA对B取余
A&BA和B按位取与
A|BA和B按位取或
A^BA和B按位取异或
~AA按位取反

案例实操:查询出所有员工的薪水后加1显示。

select sal + 1 from emp;

5.2.2 数学函数

函数描述
ceil不小于参数的最小整数
floor不大于参数的最大整数
round四舍五入
round(a,b)保留b位小数的四舍五入
random0到1之间的随机shu’zhi

案例实操:保留一位小数。

select round(2.35,1);

5.2.3 字符串函数

1)substr或substring:截取字符串

语法一:substr(text A, int start)
说明:返回字符串A从start位置到结尾的字符串
语法二:substr(text A, int start, int len)
说明:返回字符串A从start位置开始,长度为len的字符串
案例实操:
(1)获取第二个字符以后的所有字符
select substr('helloworld',2);
输出:
elloworld

2)replace :替换

语法:replace(text A, text B, text C)
说明:将字符串A中的子字符串B替换为C。
select replace('atguigu', 'a', 'A');
输出:
Atguigu

3)repeat:重复字符串

语法:repeat(textA, int n)
说明:将字符串A重复n遍。
select repeat('123', 3);
输出:
123123123

4)split_part :字符串切割

语法:split_part(text str, text pat,int field)
说明:按照正则表达式pat匹配到的内容分割str,返回分割后的第field个字符。
select split_part('a-b-c-d','-',2);
输出:
b

5)concat :拼接字符串

语法:concat(text A, text B, text C, ……)
说明:将A,B,C……等字符拼接为一个字符串
select concat('beijing','-','shanghai','-','shenzhen');
输出:
beijing-shanghai-shenzhen

6)concat_ws:以指定分隔符拼接字符串

语法:concat_ws(text A, text…)
说明:使用分隔符A拼接多个字符串,或者一个数组的所有元素。
select concat_ws('-','beijing','shanghai','shenzhen');
输出:
beijing-shanghai-shenzhen

5.2.4 日期函数

1)current_date:当前日期

select current_date;
输出:
2023-02-15

2)current_timestamp:当前的日期加时间,并且精确的毫秒

select current_timestamp;
输出:
2023-02-15 13:50:28.144287+08

3)date_part(text,timestamp):根据输入的text获取对应的年月日时分秒

select date_part('hour',current_timestamp);
输出:
13

4)age:两个日期相差的天数(结束日期减去开始日期的天数)

​ 语法:age(timestamp enddate, timestamp startdate) ,返回值使用年和月,不只是天数。
​ 案例实操:
select age(timestamp '2024-03-16', timestamp '2023-02-15');
输出:
1 year 1 mon 1 day

5)to_char:转换日期格式

​ 语法:to_char(timestamp startdate,text )
​ 案例实操:
select to_char(now(),'yyyymmdd');
输出:
20230215

6)日期加减

对应的日期 + interval text
案例实操:
select timestamp '203-02-15' + interval '2 days';
输出:
2023-02-17 00:00:00

5.2.5 流程控制函数

1、case when:条件判断函数

语法:case when a then b [when c then d]* [else e] end
返回值:T
说明:如果a为true,则返回b;如果c为true,则返回d;否则返回 e

select case when 1=2 then 'tom' when 2=2 then 'mary' else 'tim' end; 
mary

案例实现:

1)数据准备
namedept_idsex
悟空A
大海A
宋宋B
凤姐A
婷姐B
婷婷B
2)需求

求出不同部门男女各多少人。结果如下:
dept_Id 男 女
A 2 1
B 1 2

3)在/home/gpadmin/software/datas路径上创建emp_sex.txt,并导入数据

[gpadmin@hadoop103 datas]$ vim emp_sex.txt
悟空 A 男
大海,A,男
宋宋,B,男
凤姐,A,女
婷姐,B,女
婷婷,B,女

4)创建表并导入数据
-- 建表
create table emp_sex(
    name varchar(100),     --姓名
    dept_id varchar(100), --部门id
    sex varchar(10)       --性别
);

-- 导入数据
copy emp_sex FROM '/home/gpadmin/software/datas/emp_sex.txt' delimiter '\t';
5)按需求查询数据
select 
    dept_id,
    sum(case sex when '男' then 1 else 0 end) male_count,
    sum(case sex when '女' then 1 else 0 end) female_count
from emp_sex
group by dept_id;

5.3 行列转换函数

5.3.1 行转列函数

有时候我们需要将一个列的字符串按照某个分隔符将其拼接起来,就用到了string_agg()函数。
语法:string_agg(column,parten)
案例实操:
select string_agg(ename,'-') from emp;
输出:
张三-李四-王五-赵六-侯七-马八-金九-银十-小芳-小明-小李-小元-小海-小红明

5.3.2 列转行函数

​ 语法:regexp_split_to_table(column,parten)
​ 案例实操:
select regexp_split_to_table('a-b-c-d','-');
输出:

a
b
c
d

5.3.3 案例演示

1.数据准备

1)表结构

moviecategory
《疑犯追踪》悬疑,动作,科幻,剧情
《Lie to me》悬疑,警匪,动作,心理,剧情
《战狼2》战争,动作,灾难

2)建表语句

create table movie_info(
    movie varchar(100),     --电影名称
    category varchar(100)   --电影分类
);

3)装载语句

insert into movie_info values ('《疑犯追踪》', '悬疑,动作,科幻,剧情'),
       ('《Lie to me》', '悬疑,警匪,动作,心理,剧情'),
       ('《战狼2》', '战争,动作,灾难');
2. 需求

1)需求说明

根据上述电影信息表,统计各分类的电影数量,期望结果如下:

剧情2
动作3
心理1
悬疑2
战争1
灾难1
科幻1
警匪1

2)答案

select regexp_split_to_table(category, ',') as category_name, count(*) as cnt
from movie_info
group by category_name

5.4 窗口函数

5.4.1 概述

窗口函数,能为每行数据划分一个窗口,然后对窗口范围内的数据进行计算,最后将计算结果返回给该行数据。

5.4.2 常用窗口函数

按照功能,常用窗口可划分为如下几类:聚合函数、跨行取值函数、排名函数。

1)聚合函数

max:最大值。
min:最小值。
sum:求和。
avg:平均值。
count:计数。

2)跨行取值函数

(1)lead和lag

在这里插入图片描述

注:lag和lead函数不支持自定义窗口。

(2)first_value和last_value

在这里插入图片描述

3)排名函数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注:rank 、dense_rank、row_number不支持自定义窗口。

5.4.3 案例实操

1)数据准备

(1)创建表

create table order_info
(
    order_id     varchar(100), --订单id
    user_id      varchar(100), -- 用户id
    user_name    varchar(100), -- 用户姓名
    order_date   varchar(100), -- 下单日期
    order_amount int     -- 订单金额
);

(2)插入语句

insert into order_info
values ('1', '1001', 'songsong', '2022-01-01', '10'),
       ('2', '1002', 'cangcang', '2022-01-02', '15'),
       ('3', '1001', 'songsong', '2022-02-03', '23'),
       ('4', '1002', 'cangcang', '2022-01-04', '29'),
       ('5', '1001', 'songsong', '2022-01-05', '46'),
       ('6', '1001', 'songsong', '2022-04-06', '42'),
       ('7', '1002', 'cangcang', '2022-01-07', '50'),
       ('8', '1001', 'songsong', '2022-01-08', '50'),
       ('9', '1003', 'huihui', '2022-04-08', '62'),
       ('10', '1003', 'huihui', '2022-04-09', '62'),
       ('11', '1004', 'linlin', '2022-05-10', '12'),
       ('12', '1003', 'huihui', '2022-04-11', '75'),
       ('13', '1004', 'linlin', '2022-06-12', '80'),
       ('14', '1003', 'huihui', '2022-04-13', '94');
2)需求

(1)统计每个用户截至每次下单的累积下单总额

select
    order_id,
    user_id,
    user_name,
    order_date,
    order_amount,
    sum(order_amount) over(partition by user_id order by order_date rows between unbounded preceding and current row) sum_so_far
from order_info;

(2)统计每个用户每次下单距离上次下单相隔的天数(首次下单按0天算)

select
    order_id,
    user_id,
    user_name,
    order_date,
    order_amount,
    case when age(cast(order_date as timestamp),cast(last_order_date as timestamp)) is null then '0'
         else age(cast(order_date as timestamp),cast(last_order_date as timestamp)) 
    end diff
from
(
    select
        order_id,
        user_id,
        user_name,
        order_date,
        order_amount,
        lag(order_date,1,null) over(partition by user_id order by order_date) last_order_date
    from order_info
)t1;

(3)查询所有下单记录以及每个下单记录所在月份的首/末次下单日期

select
    order_id,
    user_id,
    user_name,
    order_date,
    order_amount,
    first_value(order_date) over(partition by user_id,substring(order_date,1,7) order by order_date) first_date,
    last_value(order_date) over(partition by user_id,substring(order_date,1,7) order by order_date rows between unbounded preceding and unbounded following) last_date
from order_info;

(5)为每个用户的所有下单记录按照订单金额进行排名

select
    order_id,
    user_id,
    user_name,
    order_date,
    order_amount,
    rank() over(partition by user_id order by order_amount desc) rk,
    dense_rank() over(partition by user_id order by order_amount desc) drk,
    row_number() over(partition by user_id order by order_amount desc) rn
from order_info;

六、其他

er by order_date rows between unbounded preceding and current row) sum_so_far
from order_info;


**(2)统计每个用户每次下单距离上次下单相隔的天数(首次下单按0天算)**

```sql
select
    order_id,
    user_id,
    user_name,
    order_date,
    order_amount,
    case when age(cast(order_date as timestamp),cast(last_order_date as timestamp)) is null then '0'
         else age(cast(order_date as timestamp),cast(last_order_date as timestamp)) 
    end diff
from
(
    select
        order_id,
        user_id,
        user_name,
        order_date,
        order_amount,
        lag(order_date,1,null) over(partition by user_id order by order_date) last_order_date
    from order_info
)t1;

(3)查询所有下单记录以及每个下单记录所在月份的首/末次下单日期

select
    order_id,
    user_id,
    user_name,
    order_date,
    order_amount,
    first_value(order_date) over(partition by user_id,substring(order_date,1,7) order by order_date) first_date,
    last_value(order_date) over(partition by user_id,substring(order_date,1,7) order by order_date rows between unbounded preceding and unbounded following) last_date
from order_info;

(5)为每个用户的所有下单记录按照订单金额进行排名

select
    order_id,
    user_id,
    user_name,
    order_date,
    order_amount,
    rank() over(partition by user_id order by order_amount desc) rk,
    dense_rank() over(partition by user_id order by order_amount desc) drk,
    row_number() over(partition by user_id order by order_amount desc) rn
from order_info;

六、其他

1 数据迁移

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/884204.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ARM_5_UART总线接口实验

一、总线相关的概念 1.1、总线的含义 定义&#xff1a;总线是不同设备间通信的桥梁 比如&#xff1a; PC ---------------- UART总线------------------ SOC SOC&#xff08;stm32mp157a&#xff09; --------------- IIC总线 ---------------- 空气温湿度芯片&#xff0…

【C++报错已解决】std::ios_base::failure

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

“JY901传感器“学习笔记

目录 一、产品概述 二、产品功能介绍 2.1、轴向说明 2.2、模块校准 2.3、姿态角 2.4、大地坐标系、地心地固坐标系、站心坐标系 三、参考文献 一、产品概述 模块集成高精度的陀螺仪、加速度计、地磁场传感器&#xff0c;采用高性能的微处理器和先进的动力解算与卡尔曼动…

征程6 上基于 DEB 工具实现包管理

1.引言 在开发、调测过程中&#xff0c;开发人员需要将系统软件、应用软件部署到 Soc 板端&#xff0c;以用于运行调试。传统的部署方式是通过解压复制或者调用部署脚本。这样的部署方式需要有着方式不统一、维护投入大的缺点。 在 linux 系统上&#xff0c;大多采用包管理的…

罕见,回复问询后闪电终止,业绩存下滑风险

《IPO魔女》认为&#xff0c;和美精艺利润低且大幅波动&#xff0c;报告期公司毛利率持续大幅下滑。而2023年同行业的上市公司均出现了业绩大幅下滑的情况&#xff0c;还未上市的和美精艺恐怕也存在业绩下滑的风险。此外&#xff0c;2020年至2022年&#xff0c;和美精艺研发投入…

docker的harbor仓库登录问题

目录 一、问题描述 二、证书信任问题 三、DNS解析问题 四、解决 参考链接&#xff1a;Docker login Harbor报错解决&#xff1a;Error response from daemon: Get https:..-阿里云开发者社区 一、问题描述 问题&#xff1a; 挂机或者挂机重启之后harbor登录不上 查看日…

【质优价廉】GAP9 AI算力处理器赋能智能可听耳机,超低功耗畅享未来音频体验!

当今世界&#xff0c;智能可听设备已经成为了流行趋势。随后耳机市场的不断成长起来&#xff0c;消费者又对AI-ANC&#xff0c;AI-ENC&#xff08;环境噪音消除&#xff09;降噪的需求逐年增加&#xff0c;但是&#xff0c;用户对于产品体验的需求也从简单的需求&#xff0c;升…

【Qt笔记】QStackedWidget控件详解

目录 引言 一、基础功能 二、属性设置 2.1 属性介绍 2.2 代码示例 2.3 代码解析 三、常用API 3.1 添加子部件 3.2 插入子部件 3.3 移除子部件 3.4 设置当前页面索引值 3.5 设置当前显示子部件 3.6 返回索引处子部件指针 3.7 返回子部件索引值 四、信号与槽 4.…

代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 图论part08**拓扑排序精讲**题目&#xff1a;117. 软件构建拓扑排序的背景解题思路&#xff1a;模拟过程 **dijkstra&#xff08;朴素版&#xff09;精讲**题目&#xff1a;47. 参加科学大会解题思…

OpenCV视频I/O(5)视频采集类VideoCapture之从视频流中获取下一帧的函数grab()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 从视频文件或捕获设备中抓取下一帧。 grab() 函数是 OpenCV 中 VideoCapture 类的一个成员函数&#xff0c;用于从视频流中获取下一帧而不立即检…

Android Studio 真机USB调试运行频繁掉线问题

一、遇到问题 Android Studio使用手机运行项目时&#xff0c;总是频繁掉线&#xff0c;连接很不稳定&#xff0c;动不动就消失&#xff0c;基本上无法使用 二、问题出现原因 1、硬件问题&#xff1a;数据线 换条数据线试试&#xff0c;如果可以&#xff0c;那就是数据线的…

element plus block报错

解决&#xff1a; ::v-deep input[aria-hidden"true"] {display: none !important }

9.3 Linux_I/O_文件I/O相关函数

打开与关闭 1、打开文件 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);返回值&#xff1a;成功返回文件描述符&#xff0c;失败返回EOF pathname&#xff1a;文件路径 flags&#xff1a;标志&#xff0c;其中O_RDO…

《面向对象是怎样工作的》笔记

6、1、在面向对象的世界中&#xff0c;我们需要事先为所有的行动准备好方法并通过消息传递来调用方法&#xff0c;这样事物才会开始运作。 2、实际上&#xff0c;类、继承和多态应该被明确定义为能提高软件的可维护性和可重用行的结构。类将变量和子程序汇总在一起&#xff0c…

Vue 技术入门 day1 模版语法、数据绑定、事件处理、计算属性与监视、class和style绑定、条件渲染v-if/v-show、列表渲染v-for

目录 1.Vue 核心 1.1. Vue 简介 1.1.1 介绍与描述 1.1.2 Vue 的特点 1.2 模板语法 1.2.1 模板的分类 1.2.2 插值语法 1.2.3 指令语法 1.2.4 实例 1.3 数据绑定 1.3.1 单向数据绑定 1.3.2 双向数据绑定 1.3.3 MVVM 模型 1.3.4 data与el的2种写法 1.3.5 实例 1.3.…

信息安全工程师(25)网络安全体系框架主要组成和建设内容

一、主要组成 信息安全战略&#xff1a;确立组织的信息安全目标和方向&#xff0c;指导整个网络安全体系的建设和运营。信息安全政策和标准&#xff1a;制定和执行一系列信息安全政策、标准和规范&#xff0c;确保网络安全活动有法可依、有章可循。信息安全管理&#xff1a;包括…

网站建设中常见的网站后台开发语言有哪几种,各自优缺点都是什么?

市场上常见的网站后台开发语言有PHP、Python、JavaScript、Ruby、Java和.NET等。这些语言各有其独特的优缺点&#xff0c;适用于不同的开发场景和需求。以下是对这些语言的具体介绍&#xff1a; PHP 优点&#xff1a;PHP是一种广泛用于Web开发的动态脚本语言&#xff0c;特别适…

《论文阅读》 用于产生移情反应的迭代联想记忆模型 ACL2024

《论文阅读》 用于产生移情反应的迭代联想记忆模型 ACL2024 前言简介任务定义模型架构Encoding Dialogue InformationCapturing Associated InformationPredicting Emotion and Generating Response损失函数问题前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦…

成都睿明智科技有限公司赋能商家高效变现

在这个日新月异的数字时代&#xff0c;抖音电商正以不可阻挡之势崛起&#xff0c;成为众多品牌与商家竞相角逐的新战场。在这片充满机遇与挑战的蓝海中&#xff0c;成都睿明智科技有限公司如同一颗璀璨新星&#xff0c;凭借其专业的服务、创新的策略和敏锐的市场洞察&#xff0…

NLP 文本分类任务核心梳理

解决思路 分解为多个独立二分类任务将多标签分类转化为多分类问题更换 loss 直接由模型进行多标签分类 数据稀疏问题 标注更多数据&#xff0c;核心解决方案&#xff1a; 自己构造训练样本 数据增强&#xff0c;如使用 chatGPT 来构造数据更换模型 减少数据需求增加规则弥补…