交叉联接在两个集合的元组上执行笛卡尔乘积。
SELECT *
FROM Table1
CROSS JOIN Table2
哪些情况下此类SQL操作特别有用?
交叉联接在两个集合的元组上执行笛卡尔乘积。
SELECT *
FROM Table1
CROSS JOIN Table2
哪些情况下此类SQL操作特别有用?
Answers:
如果您要完全填充“网格”,例如特定服装的尺寸和颜色信息,请执行以下操作:
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 FROM读取时间。 。)他意识到自己仍然还有DUAL桌子,并使用了它。一段时间后,他厌倦了看到两次打印时间,因此最终删除了其中一行。
Oracle的其他人开始使用他的表,最终决定将其包括在标准Oracle安装中。
这就解释了为什么一个表的唯一意义是具有一行的表的名称为何表示“两个”。
关键是“告诉我所有可能的组合”。我将它们与其他计算字段结合使用,然后对其进行了排序/过滤。
例如,假设您正在构建套利(交易)应用程序。您有卖家以一定价格提供产品,而买家以一定价格要求产品。您对产品密钥进行交叉联接(以匹配潜在的买方和卖方),计算成本和价格之间的价差,然后对desc进行排序。以此为您(中间人)执行最有利可图的交易。当然,几乎总是会有其他边界过滤器条件。
这是使用交叉联接创建交叉表报表的一种有趣方法。我在Joe Celko的SQL For Smarties中找到了它,并使用了几次。它确实需要一些设置,但是值得花时间投入。
您可以使用CROSS JOIN来执行以下操作:-生成用于测试目的的数据-合并所有属性-您需要使用所有可能的组合,例如血型(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;