开源 BI 实践:简化多表关联查询
DQL 重要的作用是解决表间关联,有了上一期配置好的元数据,我们就可以来操练一些 DQL 语句,下面看几种不同关联方式的例子,看看它是如何简化关联的。
多级关联
先跑出界面,仔细观察其中的元数据树,可以看到所有表、以及表的关联关系都在树上体现出来了,只要是能关联上的数据,无论涉及几个表,都可以逐级找到。
下面想对比各个国家客户的订单数据,这涉及到订单、客户、国家、区域表。把订单表展开后,这四个表的信息都能找到:
生成的 DQL 语句:
SELECT
T1. 客户编号. 客户名 客户名
,T1. 客户编号. 国家编号. 国家名 国家名
,T1.客户编号. 国家编号. 区域编号. 区域名 区域名
,T1. 总价 总价
,T1. 订单优先级 订单优先级
FROM
订单表 T1
其中的区域名,可以理解为订单的客户的国家的区域名称:
实现相同功能的 SQL 语句如下:
SELECT
T_1_2.C_NAME ` 客户名 `
,T_1_3.N_NAME ` 国家名 `
,T_1_4.R_NAME ` 区域名 `
,T_1_1.O_TOTALPRICE ` 总价 `
,T_1_1.O_ORDERPRIORITY ` 订单优先级 `
FROM
orders T_1_1
LEFT JOIN
customer T_1_2 ON T_1_1.O_CUSTKEY=T_1_2.C_CUSTKEY
LEFT JOIN
nation T_1_3 ON T_1_2.C_NATIONKEY=T_1_3.N_NATIONKEY
LEFT JOIN
region T_1_4 ON T_1_3.N_REGIONKEY=T_1_4.R_REGIONKEY
SQL 中用 JOIN 把四个表关联到一起后获取各表需要的信息。
自关联
想了解雇员的多级上级信息,各级雇员都在雇员表里,只是用上级字段指向上级的那条记录(外键到雇员表自身):
DQL 语句:
SELECT
T1. 雇员姓名 雇员姓名
,T1. 职务 职务
,T1. 上级. 雇员姓名 上级姓名
,T1. 上级. 职务 上级职务
,T1. 上级. 性别 上级性别
,T1. 上级. 上级. 雇员姓名 上级的上级姓名
FROM
雇员 T1
SQL 语句:
SELECT
T_1_1."姓名" "雇员姓名"
,T_1_1."职务" "职务"
,T_1_2."姓名" "上级姓名"
,T_1_2."职务" "上级职务"
,T_1_2."性别" "上级性别"
,T_1_3."姓名" "上级的上级姓名"
FROM
"雇员" T_1_1
LEFT JOIN
"雇员" T_1_2 ON T_1_1."上级"=T_1_2."雇员 ID"
LEFT JOIN
"雇员" T_1_3 ON T_1_2."上级"=T_1_3."雇员 ID"
这个查询虽然只涉及雇员一个表,但要用它三次,T_1_1 代表的是当前雇员,T_1_2 代表的是上级, T_1_3 代表的是上级的上级,把它们 JOIN 后,就把当前雇员、上级、上级的上级拼到一条记录里了。
在 DQL 中是单表查询,上级,上级的上级的信息清晰自然。
互关联
想要查询员工和经理的信息,经理信息虽然也在员工表,但谁是哪个部门的经理存储在部门表里,员工表的部门字段外键到部门表,部门的经理字段又外键回员工表,两表互相关联:
DQL 语句:
SELECT
T1. 员工姓名 员工姓名
,T1. 国籍 员工国籍
,T1. 部门. 部门名称 部门名称
,T1. 部门. 经理. 员工姓名 经理姓名
,T1. 部门. 经理. 国籍 经理国籍
FROM
员工 T1
SQL 语句:
SELECT
T_1_1.NAME "员工姓名"
,T_1_1.COUNTRY "员工国籍"
,T_1_2.NAME "部门名称"
,T_1_3.NAME "经理姓名"
,T_1_3.COUNTRY "经理国籍"
FROM
EMPLOYEE T_1_1
LEFT JOIN
DEPARTMENT T_1_2 ON T_1_1.DEPTID=T_1_2.ID
LEFT JOIN
EMPLOYEE T_1_3 ON T_1_2.MANAGER=T_1_3.ID
DQL 里理解为员工的部门的经理;
SQL 里理解为代表员工的员工表 T_1_1、部门表、代表经理的员工表 T_1_3 关联到一起;
显然 DQL 的理解更为容易。
重复关联
要查询发货记录里的发货城市、收货城市,发货记录表里会用两个城市字段都外键到同一个维表(城市表):
DQL 语句:
SELECT
T1. 发货单号 发货单号
,T1. 发货日期 发货日期
,T1. 发货城市. 名称 发货城市
,T1. 收货城市. 名称 收货城市
FROM
发货记录 T1
SQL 语句:
SELECT
T_1_1."发货单号" "发货单号"
,T_1_1."发货日期" "发货日期"
,T_1_2."城市" "发货城市"
,T_1_3."城市" "收货城市"
FROM
"发货记录" T_1_1
LEFT JOIN
"城市" T_1_2 ON T_1_1."发货城市"=T_1_2."城市编码"
LEFT JOIN
"城市" T_1_3 ON T_1_1."收货城市"=T_1_3."城市编码"
DQL 里理解为发货记录的发货城市、收货城市;
SQL 里理解为发货记录表、代表发货城市的城市表 T_1_2、代表收货城市的城市表 T_1_3 做关联。
同维表
要查客户信息,主要信息在客户表,对客户的补充信息在 VIP 客户表,两表是一对一的关系 (元数据中设置客户表主键外键到 VIP 客户主键),DQL 中会把它们自然合并在一起,称作同维表,DQL 从客户表就能直接查询两表信息:
DQL 语句:
SELECT
T1. 客户名称 客户名称
,T1. 联系人姓名 联系人姓名
,T1.VIP 级别 VIP 级别
,T1.VIP 折扣率 VIP 折扣率
FROM
客户 T1
SQL 语句:
SELECT
T_1."客户名称" "客户名称"
,T_1."联系人姓名" "联系人姓名"
,T_1_1."VIP 级别" "VIP 级别"
,T_1_1."折扣率" "VIP 折扣率"
FROM
"客户" T_1
LEFT JOIN
"VIP 客户" T_1_1 ON T_1."客户 ID"=T_1_1."客户 ID"
SQL 中需要对两表做关联查询。
多字段关联
要查订单的发货情况,发货记录表外键到订单明细表有两个关联字段(订单和商品):
这种多字段关联在 DQL 中也可以像单表一样查询:
DQL 语句:
SELECT
T1. 发货单号 发货单号
,T1. 收货日期 收货日期
,T1. 订单信息. 数量 数量
,T1. 订单信息. 折扣 折扣
FROM
发货记录 T1
SQL 语句:
SELECT
T_1_1."发货单号" "发货单号"
,T_1_1."收货日期" "收货日期"
,T_1_2."数量" "数量"
,T_1_2."折扣" "折扣"
FROM
"发货记录" T_1_1
LEFT JOIN
"订单明细" T_1_2 ON T_1_1."订单 ID"=T_1_2."订单 ID" AND T_1_1."产品 ID"=T_1_2."产品 ID"
SQL 里书写多字段关联条件时,注意要写全,不要漏写关联字段的等值条件。
按维对齐关联
想按照日期统计入库数量、支付金额,订单金额。入库数量按照入库单表的入库日期统计;支付金额按照支付单表的支付日期统计;订单金额按照订单表里的发货日期 (也可以如下图切换成按照签单日期) 统计:
这个 DQL 语句里也有了 JOIN,但注意这和 SQL 的笛卡尔积 JOIN 不一样,DQL 的 JOIN 是每个表先分别按日期维汇总,汇总之后按照日期再对齐成最后的结果集,而 SQL 的 JOIN 是笛卡尔积成一个大结果集后,再过滤去掉不符合条件的记录,然后再按照维度字段分组汇总:
SELECT
T1.sum(入库数量) 入库数量求和
,T2.sum(支付金额) 支付金额求和
,T3.sum(明细金额) 订单明细金额求和
ON 日 日期
FROM
入库单 T1 BY T1. 入库日期
JOIN
支付单 T2 BY T2. 支付日期
JOIN
订单明细 T3 BY T3. 订单. 发货日期
SQL 语句:
SELECT
T_1.F_1 "日期"
,T_1.F_2 "入库数量求和"
,T_2.F_2 "支付金额求和"
,T_3.F_2 "订单明细金额求和"
FROM
(SELECT T_1."入库日期" F_1,sum(T_1."入库数量") F_2 FROM "入库单" T_1 GROUP BY T_1."入库日期") T_1
JOIN
(SELECT T_2."支付日期" F_1,sum(T_2."支付金额") F_2 FROM "支付单" T_2 GROUP BY T_2."支付日期") T_2 ON T_1.F_1=T_2.F_1
JOIN
(SELECT T_3_3."发货日期" F_1,sum((T_3_2."单价"*(1-T_3_1."折扣")*T_3_1."数量"))F_2 FROM "订单明细" T_3_1 LEFT JOIN "产品" T_3_2 ON T_3_1."产品 ID"=T_3_2."产品 ID" LEFT JOIN "订单" T_3_3 ON T_3_1."订单 ID"=T_3_3."订单 ID" GROUP BY T_3_3."发货日期") T_3 ON T_1.F_1=T_3.F_1
上面这个查询还没涉及各个表额外的条件,SQL 里写关联字段的等值条件 (ON) 就有好几个,因为疏忽随便漏掉一个都会是错误结果,而 DQL 中各个表先独自算的方式就不容易出错。
后记
探讨上面这些不同方式的关联查询,有助于加深对 DQL 的理解。但在元数据中设置表关系时、界面用户用元数据树做多维分析时没必要刻意区分是哪种关联方式,都是自然而然的,多表关联的需求大多变成了单表查询,既不会理解错,也不会用错,业务人员自然就能灵活地自己搞定更多多维分析需求。
对润乾产品感兴趣的小伙伴,一定要知道软件还能这样卖哟性价比还不过瘾? 欢迎加入好多乾计划。
这里可以低价购买软件产品,让已经亲民的价格更加便宜!
这里可以销售产品获取佣金,赚满钱包成为土豪不再是梦!
这里还可以推荐分享抢红包,每次都是好几块钱的巨款哟!
来吧,现在就加入,拿起手机扫码,开始乾包之旅
嗯,还不太了解好多乾?