交叉连接有什么用途?
-
03-07-2019 - |
题
交叉连接对两个集合的元组执行笛卡尔积。
SELECT *
FROM Table1
CROSS JOIN Table2
哪些情况下这样的 SQL 操作特别有用?
解决方案
如果你有一个“网格”您想要完全填充,例如特定服装的尺寸和颜色信息:
select
size,
color
from
sizes CROSS JOIN colors
也许您想要一个包含当天每分钟行的表,并且您希望使用它来验证每分钟执行一个过程,因此您可能会跨越三个表:
select
hour,
minute
from
hours CROSS JOIN minutes
或者您有一套标准报告规范要应用于一年中的每个月:
select
specId,
month
from
reports CROSS JOIN months
将这些视图保留为视图的问题在于,在大多数情况下,您不需要完整的产品,特别是衣服方面。您可以在查询中添加 MINUS
逻辑,以删除某些您没有携带的组合,但您可能会发现以其他方式填充表格更容易,而不是使用笛卡尔积。
此外,您最终可能会尝试对可能比您想要的行多一些的表进行交叉连接,或者可能部分或完全缺少 WHERE
子句。在这种情况下,您的DBA会立即通知您遗漏。通常他或她会不高兴。
其他提示
对于大多数数据库查询,您通常不需要完整的笛卡尔积。关系数据库的全部功能在于,您可以应用您可能感兴趣的任何限制,以避免从数据库中删除不必要的行。
我想你可能想要的一个人为设想的例子是,如果你有一张员工表和一份需要做的工作表,并希望看到一个员工的所有可能的工作分配给一个工作。
生成测试数据。
好吧,这可能不会回答这个问题,但是,如果这是真的(我甚至不确定)这是一段有趣的历史。
在Oracle的早期,其中一位开发人员意识到他需要复制表格中的每一行(例如,它可能是一个事件表,他需要将其单独更改为“启动事件”并且“结束事件”条目)。他意识到如果他有一个只有两排的桌子,他可以做一个交叉连接,只选择第一个表中的列,并得到他所需要的。所以他创建了一个简单的表格,他自然而然地称之为“DUAL”。
后来,他需要做一些只能通过表中的选择来完成的事情,即使动作本身与桌子无关,(也许他忘了他的手表,想通过SELECT SYSDATE读取时间)来自...)他意识到他仍然躺着他的DUAL桌子,然后使用它。过了一会儿,他厌倦了看到打印两次的时间,所以他最终删除了其中一行。
Oracle的其他人开始使用他的表,最终决定将其包含在标准的Oracle安装中。
这就解释了为什么一个表的唯一意义就是它有一行的名称意味着“两个”。
关键是“告诉我所有可能的组合”。我已经将这些与其他计算字段结合使用,然后对它们进行排序/过滤。
例如,假设您正在构建套利(交易)应用程序。您有卖家以实惠的价格提供产品,买家需要付费购买产品。您在产品密钥上进行交叉连接(以匹配潜在的买方和卖方),计算成本和价格之间的差价,然后对desc进行排序。在此,给你(中间人)最有利可图的交易来执行。当然,你几乎总是会有其他的边界过滤标准。
采用数字表格,数字0-9有10行。您可以在该表上使用交叉连接几次,以获得具有所需行数的结果,并且结果编号相应。这有很多用途。例如,您可以将它与datadd()函数结合使用,以获取给定年份中每天的集合。
这是一种使用交叉联接的有趣方式创建交叉表报告。我在 Joe Celko的SQL For Smarties 中找到了它,并且多次使用它。它确实需要一些设置,但值得投入时间。
想象一下,您想要针对特定的商品和日期组合(价格、可用性等)发出一系列查询。您可以将项目和日期加载到单独的临时表中,并使查询交叉连接表。这可能比枚举 IN 子句中的项目和日期更方便,特别是因为某些数据库限制 IN 子句中的元素数量。
你可以用它 交叉连接 到:- 生成用于测试目的的数据 - 结合所有属性 - 您需要所有可能的组合,例如血型(A,B,..)与Rh-/+等...--根据您的目的调整它;) - 我不是这方面的专家;)
CREATE TABLE "HR"."BL_GRP_01"
("GR_1" VARCHAR2(5 BYTE));
REM INSERTING into BL_GRP_01
SET DEFINE OFF;
Insert into BL_GRP_02 (GR_1) values ('A');
Insert into BL_GRP_02 (GR_1) values ('B');
Insert into BL_GRP_02 (GR_1) values ('O');
Insert into BL_GRP_01 (GR_1) values (NULL);
CREATE TABLE "HR"."BL_GRP_02"
("GR_1" VARCHAR2(5 BYTE));
REM INSERTING into BL_GRP_02
SET DEFINE OFF;
Insert into BL_GRP_02 (GR_1) values ('A');
Insert into BL_GRP_02 (GR_1) values ('B');
Insert into BL_GRP_02 (GR_1) values ('O');
Insert into BL_GRP_02 (GR_1) values (NULL);
CREATE TABLE "HR"."RH_VAL_01"
("RH_VAL" VARCHAR2(5 BYTE));
REM INSERTING into RH_VAL_01
SET DEFINE OFF;
Insert into RH_VAL_01 (RH_VAL) values ('+');
Insert into RH_VAL_01 (RH_VAL) values ('-');
Insert into RH_VAL_01 (RH_VAL) values (NULL);
select distinct a.GR_1 || b.GR_1 || c.RH_VAL as BL_GRP
from BL_GRP_01 a, BL_GRP_02 b, RH_VAL_01 c
GROUP BY a.GR_1, b.GR_1, c.RH_VAL;
- 为没有公共 id 的 2 个表创建联接,然后使用 max() 等对其进行分组。找到最高可能的组合