交叉连接在两组的元组上执行笛卡尔积。
SELECT *
FROM Table1
CROSS JOIN Table2
哪种情况会使这种SQL操作特别有用?
答案 0 :(得分:83)
如果您想要完全填充“网格”,例如特定服装的尺寸和颜色信息:
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会立即通知您遗漏。通常他或她会不高兴。
答案 1 :(得分:13)
对于大多数数据库查询,您通常不需要完整的笛卡尔积。关系数据库的全部功能在于,您可以应用您可能感兴趣的任何限制,以避免从数据库中删除不必要的行。
我想你可能想要的一个人为设想的例子是,如果你有一张员工表和一份需要做的工作表,并希望看到一个员工的所有可能的工作分配给一个工作。
答案 2 :(得分:12)
生成测试数据。
答案 3 :(得分:11)
好吧,这可能不会回答这个问题,但是,如果这是真的(我甚至不确定)这是一段有趣的历史。
在Oracle的早期,其中一位开发人员意识到他需要复制表中的每一行(例如,它可能是一个事件表,他需要将其单独更改为“start event”和“结束事件“条目”。他意识到如果他有一个只有两排的桌子,他可以做一个交叉连接,只选择第一个表中的列,并得到他所需要的。所以他创造了一个简单的表格,他自然而然地称之为“DUAL”。
后来,他需要做一些事情,只能通过表格中的选择来完成,即使动作本身与桌子无关,(也许他忘记了他的手表并希望通过SELECT SYSDATE读取时间来自...)他意识到他仍然躺着他的DUAL桌子,然后使用它。过了一会儿,他厌倦了看到打印两次的时间,所以他最终删除了其中一行。
Oracle的其他人开始使用他的表,最终决定将其包含在标准的Oracle安装中。
这解释了为什么一个表的唯一意义就是它有一行的名称意味着“两个”。
答案 4 :(得分:7)
关键是“告诉我所有可能的组合”。我已经将这些与其他计算字段结合使用,然后对它们进行排序/过滤。
例如,假设您正在构建套利(交易)应用程序。您有卖家以实惠的价格提供产品,买家需要付费购买产品。您在产品密钥上进行交叉连接(以匹配潜在的买方和卖方),计算成本和价格之间的差价,然后对desc进行排序。在此,给你(中间人)最有利可图的交易来执行。当然,你几乎总是会有其他的边界过滤标准。
答案 5 :(得分:3)
采用数字表格,数字0-9有10行。您可以在该表上使用交叉连接几次,以获得具有所需行数的结果,并且结果编号相应。这有很多用途。例如,您可以将它与datadd()函数结合使用,以获取给定年份中每天的集合。
答案 6 :(得分:2)
这是一种使用交叉联接create a crosstab report的有趣方式。我在Joe Celko's SQL For Smarties找到了它,并且多次使用过它。它确实需要一些设置,但值得投入时间。
答案 7 :(得分:1)
想象一下,您想要针对特定项目和日期组合(价格,可用性等)发布一系列查询。您可以将项目和日期加载到单独的临时表中,并让您的查询交叉连接表。这可能比枚举IN子句中的项和日期更方便,特别是因为某些数据库限制了IN子句中的元素数。
答案 8 :(得分:1)
您可以使用它 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;