亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

Databricks SQL 數據倉庫:SQL 用戶實用指南

这张图来自 ChatGPT

对于一些不太了解 Databricks 的用户来说,可能认为它主要为 Python 或 Scala 用户设计的数据处理平台。然而,Spark SQL 的出现让 Databricks 更加适应 SQL 用户的需求,即使这些用户对 Python 或 Scala 不太熟悉。

此外,借助 Unity Catalog 或 Hive Metastore,您可以创建诸如表、视图和函数之类的典型数据仓库对象。无服务器计算可以在几秒钟内启动,这使得 Databricks 很难与一个强大的数据仓库工具区分开,就像它本身就是这样的工具一样。这些功能让 SQL 用户可以更轻松地使用 Databricks 来进行数据仓库和分析。

Databricks中的SQL工具

Databricks 的 SQL 编辑工具支持使用 Databricks SQL。我们可以编写 SQL 查询来变换或查阅数据。如图所示,我们可以浏览目录中的表、视图和函数,编写查询,并选择 Serverless SQL 仓库来运行 SQL 语句。SQL 编辑器具有智能和辅助功能,有助于编写 SQL 查询。

作者提供图片

SQL 代码可以在笔记本中执行,这可以通过利用通用集群或无服务器计算资源来实现。若要在笔记本中执行 SQL 查询,你需要在单元格顶部输入 %sql 魔法命令,让 Databricks 知道这是 SQL 语句。

使用 Databricks SQL 创建表格

Databricks SQL 提供了多种方式来在 Unity Catalog 或者 Hive Metastore 中创建表。我们可以通过引用现有的 Parquet 文件,复制现有的表,或者克隆一个表,或者通过执行带有 DDL(数据定义语言)定义的 SQL 语句来创建表。

    创建名为 clients 的表,使用 CSV 文件,位置为 '/path/to/clients';  

    创建表 clients_copy,其内容与 clients 表相同;

从文件创建表格很方便,但在数据仓库场景中,定义一个模式更好。一个明确定义的模式非常重要,因为它确保了字段名称和数据类型的统一性。这种一致性让数据模型能无缝使用,并能轻松集成到商业智能工具中。

    CREATE TABLE dbo.clients  
    (  
     client_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,  
     region_id bigint,  
     client_number VARCHAR,  
     name VARCHAR,  
     email VARCHAR,  
     phone_number VARCHAR,  
     building_number VARCHAR,  
     street_name VARCHAR,  
     birth_date date  
    );  

    ALTER TABLE clients ADD CONSTRAINT dateWithinRange CHECK (birth_date > '1900-01-01');

Delta 表在 Databricks 中支持重要的数据仓库功能,例如标识列(身份列)、约束和主键/外键。这些功能有助于设计数据模型,或从本地数据库迁移到 Databricks。通过这些功能,您可以确保数据的完整性,建立表之间的关系,并保持符合传统数据仓库实践的结构化模式。

作者供图

关于将数据加载到Databricks SQL的一些DML语句

Databricks 支持执行关键的数据操纵语言(DML)命令,用于数据操作。通过 Databricks SQL 和 Delta 表,您可以执行更新、删除或插入等关键操作,以修改表里的数据。

价值观

使用 VALUES 命令,您可以定义虚拟数据集用于测试目的或提升查询性能。它可以用在通用表表达式 (CTE) 中,通用表表达式也称为 CTE,或充当临时视图。此命令在模拟数据、执行快速测试或将小数据集集成到更大的查询中而无需创建表时非常有用。

WITH dane (a, b, c) AS (  
    VALUES ('a', 1, 8),  
           ('b', 2, 9),  
           ('a', 1, 3),  
           ('b', 2, 5),  
           ('c', 3, 5),  
           ('a', 3, 4)  
)  

SELECT * FROM dane;  

CREATE TEMP VIEW vdane AS  
    VALUES ('a', 1, 8),  
           ('b', 2, 9),  
           ('a', 1, 3),  
           ('b', 2, 5),  
           ('c', 3, 5),  
           ('a', 3, 4)  

SELECT *  
FROM  
vdane

预期的结果:

这张由作者制作

插入

Databricks SQL仅支持将INSERT INTO命令用于Delta表中。该命令在你需要截断数据并重新加载或向表中添加新数据时非常有用。此功能与其他SQL方言相似,但有一个特别有用的功能,可以通过名称映射列。

    CREATE TABLE dbo.客户
    ( 
     client_id bigint GENERATED BY DEFAULT AS IDENTITY,  
     region_id bigint,  
     client_number string,  
     name string,  
     email string,  
     phone_number string,  
     building_number string,  
     street_name string,  
     birth_date date  
    );

在 SQL 中使用 INSERT INTO 语句时带上列名:

INSERT INTO dbo.clients (client_number, name, email, phone_number, building_number, street_name, birth_date)  
SELECT  
client_number,  
name,  
email,  
phone_number,  
building_number,  
street_name,  
birth_date
从下面的代码中读取文件:
read_files(
  'abfss://[email protected]/clients/',
  format => 'csv',
  header => true,
  mode => 'FAILFAST');

模式设置为'FAILFAST',这意味着如果遇到错误将立即停止。

从 CSV 文件中,根据列名自动匹配并将数据插入到表中。

    INSERT INTO dbo.clients  
    SELECT  
     client_number,  
     name,  
     email,  
     phone_number,  
     building_number,  
     street_name,  
     birth_date  
    FROM  
    read_files(  
      'abfss://[email protected]/clients/',  
      format => 'csv',  
      header => true,  
      mode => 'FAILFAST');
合并进入

**MERGE INTO** 命令在数据仓库场景中非常有用,当我们需要从不同的地方获取数据并更新到数据仓库或数据湖时,可以使用该命令。通过使用 merge into,我们可以实现更新、插入和删除操作,使其成为管理缓慢变化维度(SCD)、Upsert 或刷新表中数据的理想工具。

创建表 Employees 如下所示,
(  
  EmployeeID int,  
  FirstName nvarchar,  
  LastName nvarchar,  
  ManagerID int   
);
    CREATE TABLE silver.raw_Employees  
    (  
      EmployeeID int,  
      FirstName string,  
      LastName string,  
      ManagerID int   
    );  

    INSERT INTO raw_Employees VALUES (1, 'Harper', 'Westbrook', NULL);  
    INSERT INTO raw_Employees VALUES (2, 'Liam', 'Carrington', 1);  
    INSERT INTO raw_Employees VALUES (3, 'Evelyn', 'Radcliffe', 1);  
    INSERT INTO raw_Employees VALUES (4, 'Mason', 'Albright', 2);  
    INSERT INTO raw_Employees VALUES (5, 'Isla', 'Whitman', 2);  
    INSERT INTO raw_Employees VALUES (6, 'Noah', 'Sterling', 3);  
    INSERT INTO raw_Employees VALUES (7, 'Ruby', 'Lennox', 3);  
    INSERT INTO raw_Employees VALUES (8, 'Caleb', 'Winslow', 5);  
    INSERT INTO raw_Employees VALUES (9, 'Avery', 'Sinclair', 6);  
    INSERT INTO raw_Employees VALUES (10, 'Oliver', 'Beckett', 6);  
    INSERT INTO raw_Employees VALUES (1, 'Harper', 'Westbrook', NULL);  
    INSERT INTO raw_Employees VALUES (2, 'Liam', 'Carrington', 1);  
    INSERT INTO raw_Employees VALUES (3, 'Evelyn', 'Radcliffe', 1);  
    INSERT INTO raw_Employees VALUES (4, 'Mason', 'Albright', 2);  
    INSERT INTO raw_Employees VALUES (5, 'Isla', 'Whitman', 2);  
    INSERT INTO raw_Employees VALUES (6, 'Noah', 'Sterling', 3);  
    INSERT INTO raw_Employees VALUES (7, 'Ruby', 'Lennox', 3);  
    INSERT INTO raw_Employees VALUES (8, 'Caleb', 'Winslow', 5);  
    INSERT INTO raw_Employees VALUES (9, 'Avery', 'Sinclair', 6);  
    INSERT INTO raw_Employees VALUES (10, 'Oliver', 'Beckett', 6);  
    INSERT INTO raw_Employees VALUES (11, 'Avery', 'Sinclair', 6);  
    INSERT INTO raw_Employees VALUES (12, 'Oliver', 'Beckett', 6);

为了将源表中不存在于目标表中的所有行插入进去,您可以使用以下 **MERGE INTO** 语句:

    MERGE INTO Employees AS 目标
    使用 raw_Employees 作为源数据
    当目标表的 EmployeeID 等于源数据表的 EmployeeID 时
    如果不匹配则插入所有列

在目标表中插入新行并根据源表更新现有行时,您可以试试以下 **MERGE INTO** 语句:

MERGE INTO 员工表 AS 员工表 USING 原始员工表 AS 原始员工表 ON 员工表.EmployeeID = 原始员工表.EmployeeID WHEN MATCHED THEN UPDATE SET * WHEN NOT MATCHED THEN INSERT *;
-- 当记录匹配时更新,当不匹配时插入新的记录
在Databricks SQL中读取文件的过程

Databricks SQL支持读取CSV、Parquet、Delta Lake、Avro等格式的文件。你可以将这些文件作为数据源,用于你的ELT/ETL流程,Databricks SQL会负责处理这些数据转换。当你刚开始接触Databricks时,如果你对Python不太熟悉,你可以利用SQL来加载数据到表中。

读文件

为了从 CSV 文件中加载数据,推荐使用 read_csv 函数。通过设置模式类型(例如 PERMISSIVEDROPMALFORMEDFAILFAST),该函数还能处理格式不正确的 CSV 记录。你可以控制系统如何处理不一致或损坏的 CSV 数据。

    SELECT * FROM read_files(  
      'abfss://[email protected]/clients/',  
      format => 'csv',  
      header => true,  
      mode => 'FAILFAST')

虽然这个功能主要用于CSV文件,但对于Parquet或Delta等格式来说,也可以使用其他语法结构。

    SELECT *  
    FROM   
    parquet.`abfss://[email protected]/clients/`

    /* 从 'abfss://[email protected]/clients/' 获取数据,这部分路径指向存储在Azure Data Lake Storage Gen2中的clients表。*/
复制

并没有一个常用的SQL函数叫做 COPY INTO ,可以直接将数据加载到表中。然而,你可以使用该命令将CSV、Parquet或Delta格式的数据加载到Delta表中。该命令可以在Databricks SQL仓库中执行,让你可以用一个简单的SQL语句来加载数据。

    CREATE TABLE silver.raw_Employees  
    (  
      EmployeeID int,  
      FirstName string,  
      LastName string,  
      ManagerID int   
    );  

    -- 创建一个名为raw_Employees的表来存放员工信息
    CREATE TABLE silver.raw_Employees  
    (  
      EmployeeID int,  
      FirstName string,  
      LastName string,  
      ManagerID int   
    );  

    -- 将数据从指定路径复制到silver.Employees表中
    COPY INTO silver.Employees  
    FROM 'abfss://[email protected]/employees/'  
    FILEFORMAT = PARQUET;
基本聚合

Databricks SQL 中的 GROUP BY 函数支持与其他 SQL 方言一样的聚合操作。您可以使用一组指定的分组表达式对行进行分组,并使用一个或多个指定的聚合函数来计算每一组行的聚合值。

使用 GROUP BY 分组

我不会详细描述Databricks SQL聚合的所有功能,但会介绍几个最有用的功能。其中之一是FILTER命令,可以用来过滤特定值以进行聚合。

假设我们要从员工表中选择IT部门的工资总和,可以使用以下SQL语句:

SELECT 
部门, 
计算IT部门员工的工资总和 AS salary

FROM 员工

GROUP BY 部门

第二个是 ALL GROUP BY. 这同样是一个简化 SQL 语句的例子。你不必在 SELECT 部分重复列出所有列,可以直接使用这个功能:

SELECT
部门,
SUM(工资) AS 工资

FROM 员工表
GROUP BY 部门

HAVING 子句根据特定条件过滤 GROUP BY 生成的结果。它常常与 GROUP BY 子句配合使用。这里,您可以看到一个实用的功能:不需要复制聚合函数,可以直接使用其别名。

    select    
    department,  
    sum(工资) 工资  

    from 员工  
    group by department  
    having sum(工资) > 0
Databricks SQL 中的 JOIN 操作

连接在 SQL 中常用于将两个或多个表的数据结合起来,以获得基于连接条件(join 条件)的预期结果。Databricks SQL 实现了许多有用的功能,这些功能来自不同的 SQL 方言,可以为你的日常工作带来帮助。

在这里,我将重点介绍Databricks SQL文档中提到的、最受支持的Databricks SQL连接。

自然联接

这种类型的连接可以使SQL语句更简洁;作用方式与INNER JOIN相同,但语法更简短。

-- 创建一个临时视图,包含员工的信息
CREATE TEMP VIEW v_employee(emp_id, name, dep_id) AS  
    VALUES(105, 'Chloe', 5),  
          (103, 'Paul' , 3),  
          (101, 'John' , 1),  
          (102, 'Lisa' , 2),  
          (104, 'Evan' , 4),  
          (106, 'Amy'  , 6);  

-- 创建一个临时视图,包含部门的信息
CREATE TEMP VIEW department(dep_id, dept_name) AS  
    VALUES(3, 'IT'),  
          (2, 'HR'      ),  
          (1, 'Marketing'  );             

-- 查询员工和部门信息,使用 dep_id 关联部门表
select *  
from  
v_employee join department using (dep_id)

结果是...

作者绘制图片

稍后加入

这种连接在你需要在一个连接操作中处理某个结果时很有用。当需要只连接重复记录中的第一条时,侧接非常理想,因为它可以在查询过程中为每一行过滤或限制结果。

    CREATE TEMP VIEW v_employee(emp_id, name, dep_id) AS  
         VALUES(105, 'Chloe', 3),  
               (103, 'Paul', 2),  
               (101, 'John', 1);  

    CREATE TEMP VIEW department(dep_id, dept_name) AS  
        VALUES(3, 'IT'),  
              (3, 'ITx'),  
              (3, 'ITxc'),  
              (2, 'HR'),  
              (1, 'Marketing');             

    SELECT emp_id, name, dep_id, dept_name  
        FROM v_employee employee  
        JOIN LATERAL (SELECT dept_name  
                        FROM department  
                        WHERE employee.dep_id = department.dep_id LIMIT 1);

结果如下:

作者供图

反对 JOIN

ANTI JOIN 并不是标准 SQL 的一部分,但在 Databricks SQL 中是可用的。它的等效命令是 NOT EXISTS 命令。这种类型的连接会过滤掉存在于连接表中的记录,也就是说,它会排除那些在连接表中存在的记录。

这种连接可以用于仅从暂存表中选择新记录,或者查找不在其他表中的记录。下面的例子展示了如何从 raw_employee 表中获取新记录。

    CREATE TEMP VIEW v_employee(emp_id, name, dep_id) AS  
         VALUES(105, 'Chloe', 3),  
               (103, 'Paul' , 2),  
               (101, 'John' , 1);  

    CREATE TEMP VIEW raw_employee(emp_id, name, dep_id) AS  
         VALUES(105, 'Chloe', 3),  
               (103, 'Paul' , 2),  
               (101, 'John' , 1),  
               (106, 'Sam' , 3),  
               (107, 'Chris' , 1)  
               ;      

    SELECT *  
        FROM raw_employee   
        LEFT JOIN v_employee employee ON employee.emp_id = raw_employee.emp_id
        WHERE employee.emp_id IS NULL;

结果是:

作者图片

半连接

SEMI JOINANTI JOIN 的工作方式是相反的,它会选择在连接表中存在的记录。这种连接方式类似于 SQL 中的 EXISTS 命令。

    CREATE TEMP VIEW v_employee(emp_id, name, dep_id) AS  
         VALUES(105, 'Chloe', 3),  
               (103, 'Paul' , 2),  
               (101, 'John' , 1); 
    -- 创建一个临时视图,包含员工ID、姓名和部门ID

    CREATE TEMP VIEW raw_employee(emp_id, name, dep_id) AS  
         VALUES(105, 'Chloe', 3),  
               (103, 'Paul' , 2),  
               (101, 'John' , 1),  
               (106, 'Sam' , 3),  
               (107, 'Chris' , 1)  
               ; 
    -- 创建另一个包含更多员工信息的临时视图

    SELECT *  
        FROM raw_employee   
        semi JOIN  v_employee employee  ON employee.emp_id = raw_employee.emp_id;
    -- 从raw_employee表中选择数据,并使用semi JOIN连接到v_employee表,基于员工ID

作者供图

Databricks SQL中的视图功能

Databricks SQL 可以创建几种不同的 SQL 视图。

时间视角

这个视图不存储任何实际的数据,仅在会话执行时可以访问。它可以用来组织复杂的查询,将复杂查询组织成小型的可查询对象。

    创建一个临时视图 sum_employees 如下:  
    select   
    部门, sum(工资) 作为 总工资  

    FROM  
    员工表  
    group by 部门;  

    选择 *  

    FROM  
    sum_employees.
看看

在 Databricks SQL 中,也是如此,与其他 SQL 引擎一样,视图仅存储创建它所用的查询定义。视图并不存储数据,但其元数据则保存在元数据目录中。

    创建视图为 sum_employees;
    select   
    部门, sum(员工工资) as 工资  

    from  
    员工  
    group by 部门;
这将创建一个名为 sum_employees 的视图,它会显示每个部门的员工工资总和。

在目录里看到的视图:

这是作者自己拍的照片

物化视图

Databricks SQL 中的物化视图是受 Unity Catalog 管理的表,允许您存储基于创建视图时使用的语句的结果。它们包含在创建或刷新时从源表获取结果的快照。您可以手动刷新物化视图,也可以设定刷新时间。

    创建名为 m_sum_employees 的物化视图:
    SELECT
    department, SUM(salary) AS 工资总额

    FROM
    employees
    GROUP BY department

在目录里看到的:

作者图片

它更新物化视图(materialized view)以便反映最新的可用数据。

刷新物化视图 `catalog.schema.view_name`;

可以使用此命令来刷新物化视图。

创建一个物化视图,并计划在每天午夜时分刷新一次。

    创建物化视图每日薪资汇总  
    使用 CRON 调度 '0 0 0 * * ? *'  
    查询  
    部门, sum(薪资) as 薪资  

    来自  
    员工表  
    按部门分组.
处理 JSON 数据

Databricks SQL支持半结构化数据的处理,允许你直接处理JSON文件。你可以使用SQL语法直接提取、转换并操作JSON数据。这种功能在处理JSON文件中常见的复杂结构化数据时特别有用。

CREATE temp view currency AS SELECT   
'  
    {"table":"A","no":"194/A/NBP/2024","生效日期":"2024-10-04","rates":  
    [  
    {"currency":"美国美元","code":"USD","mid":3.9118},  
    {"currency":"澳大利亚元","code":"AUD","mid":2.6761},  
    {"currency":"香港元","code":"HKD","mid":0.5037},  
    {"currency":"加元","code":"CAD","mid":2.8850},  
    {"currency":"新西兰元","code":"NZD","mid":2.4264},  
    {"currency":"新加坡元","code":"SGD","mid":3.0170},  
    {"currency":"欧元","code":"EUR","mid":4.3130}  
    ]  
    }  

' as raw;  

SELECT raw.rates[0].code, raw.rates[0].mid FROM currency

作者制作的图片

很多时候,只读取数组中的一个元素是不够的。通常我们需要解析整个数组,可以用 LATERAL variant_explode 函数或其他解析数组的函数来做到这一点。

这个示例展示了如何在表中存储嵌套的数据,这些数据是以数组形式存储的关于货币汇率的信息。SQL 语句通过解析 JSON 来提取货币代码及其汇率。如下面展示的,SQL 对于解析存储在 JSON 中的数据很有帮助。

    CREATE 临时视图 currency AS SELECT   
    parse_json(  
    '  
        {"table":"A","no":"194/A/NBP/2024","effectiveDate":"2024-10-04","rates":  
        [  
        {"currency":"美国 dollar","code":"USD","mid":3.9118},  
        {"currency":"澳大利亚 dollar","code":"AUD","mid":2.6761},  
        {"currency":"香港 dollar","code":"HKD","mid":0.5037},  
        {"currency":"加拿大 dollar","code":"CAD","mid":2.8850},  
        {"currency":"新西兰 dollar","code":"NZD","mid":2.4264},  
        {"currency":"新加坡 dollar","code":"SGD","mid":3.0170},  
        {"currency":"欧元","code":"EUR","mid":4.3130}  
        ]  
        }  
        ') as raw;  

    select value['mid'], value['code']  
    from   
    currency,  
    LATERAL explode(currency.raw.rates)

因此,结果是:

作者的图片

Databricks SQL 的高级特性

Databricks SQL 提供了多种高级 SQL 函数来提升数据查询能力。您可以使用各种函数来操作数组、窗口功能(如)以及表数据,使句子更加简洁流畅。

合格

Databricks SQL 提供了用于过滤诸如 ROW_NUMBER()RANK()DENSE_RANK() 等窗口函数结果的语法。通常,为了过滤窗口函数的结果,我们需要使用子查询或公用表表达式 (CTE)。QUALIFY 语句允许用户直接筛选结果,而无需使用子查询或公用表表达式。

WITH dane (id, name, age, date) AS  
(  
    SELECT 1, 'John Smith', 19, '2020-01-01'   
    UNION ALL   
    SELECT 2, 'Eva Nowak', 21, '2021-01-01'  
    UNION ALL   
    SELECT 3, 'Danny Clark', 24, '2021-01-01'  
    UNION ALL   
    SELECT 4, 'Alicia Kaiser', 25, '2021-01-01'  
    UNION ALL   
    SELECT 5, 'John Smith', 19, '2021-01-01'  
    UNION ALL   
    SELECT 6, 'Eva Nowak', 21, '2022-01-01'  
)  

SELECT   
    ROW_NUMBER() OVER (PARTITION BY name ORDER BY date) rn,  

*  
FROM  
    dane  
-- QUALIFY 语句在某些SQL方言中用于筛选特定条件,例如这里筛选rn=1的行
WHERE rn = 1;

结果是:

如图所示,作者提供图片。

炸开!

此功能将数组转换为行。由于 Databricks 不支持递归公共表表达式(CTEs),你可以使用 SEQUENCE 函数生成一系列值,再结合 EXPLODE 函数将这些值转换为行,从而创建一个日历表。

SELECT   
日期,  
date_part('YEAR', 日期) AS 年,  
date_part('MONTH', 日期) AS 月  
FROM (  
SELECT   
explode(sequence(DATE '2024-01-01', DATE '2024-12-31', INTERVAL '1 DAY')) AS 日期  
) cal

结果是...

作者的图片

侧面视图

此命令可以与 EXPLODE 函数一起使用,该函数可以生成一个虚拟表,其中包含从数组中生成的一个或多个行。LATERAL VIEW 可以将爆炸后的每一行应用于每个原始输出行。通过结合使用这些函数,您可以根据输出结果和爆炸后的数组,生成额外的行。

WITH dane (id, name, age) AS  
(  
SELECT 1, 'John Smith', 19  
UNION ALL   
SELECT 2, 'Eva Nowak', 21  
)  

SELECT   
*  
FROM  
dane  

LATERAL VIEW EXPLODE(ARRAY('A', 'B')) AS type

结果是:

作者的图片

你可以使用 LATERAL VIEW 来创建一个基于缓慢变化维度类型2(SCD2)表的快照视图。通过下面的查询,你可以生成一个捕捉月底数据用于分析和可视化的快照视图。

    WITH dane (id, name, age, date_from, date_to) AS  
    (  
    SELECT 1, 'John Smit', 19, '2024-01-01', '2024-04-01'    
    UNION ALL   
    SELECT 2, 'Eva Nowak', 21, '2024-01-01', '2024-02-01'   
    )  

     SELECT   

*  
     FROM  
     dane  

     LATERAL VIEW EXPLODE(sequence(DATE'2024-01-31', DATE'2024-03-30', INTERVAL 1 MONTH)) as date  
     WHERE  
    date BETWEEN date_from AND date_to

结果就是:

作者拍的这张图

按照...分组

此命令用于根据指定的表达式在Databricks SQL中对数据进行分区,并在每个分区内部进行排序操作。使用CLUSTER BY可以简化SQL语句查询,使其更加简洁。

    WITH dane (a, b, c) AS (  
        VALUES ('a', 1, 8),  
               ('b', 2, 9),  
               ('a', 1, 3),  
               ('b', 2, 5),  
               ('c', 3, 5),  
               ('a', 3, 4)  
    )  

    SELECT *  
    FROM  
    dane  
    CLUSTER BY a

结果是这样的:

这张图片由作者提供

表单功能

在Databricks SQL中,表值函数(TVF,Table-Valued Function)可以根据输入参数生成一组行,返回一个表,使用户能够创建可重用的逻辑。

以下是一个在Databricks SQL中根据输入的开始和结束日期生成日历表的表值函数示例。

-- 创建或替换函数 date_func,接收两个日期参数 from_date 和 to_date
CREATE OR REPLACE FUNCTION date_func(from_date date, to_date date)  
RETURNS TABLE  
RETURN SELECT date  FROM explode(sequence(DATE'2024-01-01', DATE'2024-12-31', INTERVAL 1 DAY)) AS T(date)
-- 上面这行表示从 '2024-01-01' 到 '2024-12-31' 生成每一天的日期序列,然后使用 explode 函数展开序列,这里的 explode 是一个假想的函数,实际 SQL 中可能需要使用类似生成序列的函数。

-- 下面这行是对 date_func 函数的调用,参数为 '2024-01-01' 和 '2024-01-31'
select * from date_func('2024-01-01','2024-01-31')
-- 上面这行表示从 date_func 函数中获取指定日期区间内的每一天的日期信息

就是这个结果:

图片由作者绘制

设置参数

Databricks SQL 提供了使用参数或标识符来使代码参数化的能力。我们可以使代码更通用和更灵活,或者使用参数来进行 ETL 编排。此功能在 Databricks 工作流中特别有用,比如可以在循环中从另一个任务传递参数,可以在循环中从另一个任务传递参数值。

标识符(一个标识符)

IDENTIFIER 语句允许我们动态指定表名、列名、函数名、字段名或模式名。它使我们能够了解其在不同环境中进行笔记本并行化处理或加载多个表时如何有用,例如在不同环境中的应用。

下面是一个根据用户提供的参数来选择表格的例子。

作者供图

参数设置

在 Databricks SQL 中,参数充当占位符,允许您将值传递给 SQL 查询。这些值可用于例如过滤数据、进行计算或配置源表。参数通过允许外部值(来自用户或 API)在查询执行时注入,让 SQL 查询更加灵活和可重用。

你可以使用这些参数根据用户输入或API返回的数据来过滤数据。比如,下面的代码展示了如何用参数过滤数据。

作者的图片

参数也可以用来传递动态数值到计算中。

    SELECT EmployeeID * :value, * FROM employees 

作者的图片

立即运行

EXECUTE IMMEDIATE 函数允许你动态执行包含 SQL 语句的字符串。此函数在你需要动态生成 SQL 语句时非常有帮助。

    声明 sqlStr = 'SELECT SUM(c1) FROM VALUES(?), (?) AS t(c1)';  
    声明 arg1 = 5;  // arg1 变量赋值为 5
    声明 arg2 = 6;  // arg2 变量赋值为 6
    声明 res INT;   // res 变量声明为整数类型

    立即执行 sqlStr into res 使用 arg1 , arg2;  // 将 sqlStr 中的参数值 arg1 和 arg2 立即执行并赋值给 res
    输出 res;       // 输出 res 的值

结果 :

作者供图

EXECUTE IMMEDIATE 函数的一个强大用途是可以根据从结果中检索到的值动态生成 SQL 查询。我们可以设想一种情况,从配置或元数据表中读取一个参数,然后根据该参数动态生成一个查询,以检索所需的数据显示给用户。这在数据管道场景中尤其有用,其中你需要根据参考值(如最后处理的记录 ID)逐步加载新的或变更的数据。

    声明 sqlStr = 'SELECT max(c1) FROM VALUES(1), (2) AS t(c1)';  

    声明 res INT;  

    EXECUTE IMMEDIATE sqlStr INTO res FROM;  
    SELECT res;  

    声明 sql1 = 'SELECT count(*) FROM employees WHERE 员工ID > ? ';  

    EXECUTE IMMEDIATE sql1 INTO res USING res;  
    SELECT res;
谢谢阅读!

如果你觉得这篇文章很有启发性,我邀请你点赞并拍手来表示赞赏。你可以通过在LinkedIn上点赞和拍手来表达你的支持,你的支持对我意义重大。

點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消