交叉连接有什么用途?

时间:2008-10-20 20:11:15

标签: sql database join relational-database

交叉连接在两组的元组上执行笛卡尔积。

SELECT *
FROM Table1
CROSS JOIN Table2

哪种情况会使这种SQL操作特别有用?

9 个答案:

答案 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;
  • 为两个没有公共ID的表创建一个联接,然后使用max()等将其分组,以找到可能的最高组合